This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] S/390: HW accelerated iconv module for iso-8859-1/cp37conversions


Hi,

the attached patch adds a s390-specific iconv module for iso8859-1 to
ebcdic conversions.  This particular conversion is quite important for
mainframes since all the other mainframe OSes are ebcdic based and
exchanging data with them always involves that kind of conversion.

The module uses the translate one to one instruction (troo) which has
been introduced with the z900 cpu.  z900 was the first 64 bit machine
so adding this module for s390x makes sure that the instruction is
always available.

One problem with the troo instruction is that it always needs a string
end character as input so it is not possible to unconditionally
convert a fixed number of chars.  Therefore module choses the \0 char
as ending char hoping that it appears rarely.  If the conversion is
interrupted due to the end string char the conversion for that char is
done manually.  Afterwards a jump back to the instruction continues
the conversion using troo.

Daniel Appich did comprehensive performance analysis in his diploma
thesis and measured that the conversion is accelerated by up to 40
times!

Trying to build the iconv module from the s390 sysdep directory turned
out to be rather tricky (at least for me not being familiar with the
libc build machinery). After experimenting with several makefile
variables I've ended up trying to mimic as much as necessary from the
iconvdata Makefile until the module got built.

The current Makefile installs the new module into lib/gconv/s390x and
generates a gconv-modules file which is installed into the very same
dir.  The modules therefore will not be used until the path of the
directory is appended to GCONV_PATH.

Tested on s390x.

Ok?

Bye,

-Andreas-

2009-02-23  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* s390/s390-64/iconvdata/Makefile: New file.
	* s390/s390-64/iconvdata/iso-8859-1_cp037_z900.c: New file.
	* unix/sysv/linux/s390/s390-64/Implies: Add s390/s390-64/iconvdata.


Index: libc/sysdeps/s390/s390-64/iconvdata/Makefile
===================================================================
--- /dev/null
+++ libc/sysdeps/s390/s390-64/iconvdata/Makefile
@@ -0,0 +1,30 @@
+ifeq ($(subdir),iconvdata)
+	src_name := iso-8859-1_cp037_z900
+	module_name := ISO-8859-1_CP037_Z900
+
+	$(module_name)-routines := $(src_name)
+	$(module_name)-map := gconv.map
+
+	extra-modules-left += $(module_name)
+	include extra-module.mk
+
+	extra-objs      += $(module_name).so
+	install-others  += $(inst_gconvdir)/s390x/$(module_name).so \
+			   $(inst_gconvdir)/s390x/gconv-modules
+
+	generated += gconv-modules-s390x
+	distribute += $(src_name).c
+
+$(inst_gconvdir)/s390x/$(module_name).so: $(objpfx)$(module_name).so $(+force)
+	$(do-install-program)
+
+gconv-modules-s390x: $(+force)
+	echo -n "module ISO-8859-1//	IBM037//	" > $@
+	echo $(module_name) "	1" >> $@
+	echo -n "module IBM037//	ISO-8859-1//	" >> $@
+	echo $(module_name) "	1" >> $@
+
+$(inst_gconvdir)/s390x/gconv-modules: gconv-modules-s390x $(+force)
+	$(do-install)
+
+endif
Index: libc/sysdeps/s390/s390-64/iconvdata/iso-8859-1_cp037_z900.c
===================================================================
--- /dev/null
+++ libc/sysdeps/s390/s390-64/iconvdata/iso-8859-1_cp037_z900.c
@@ -0,0 +1,212 @@
+/* Conversion between ISO 8859-1 and IBM037.
+
+   This module uses the Z900 variant of the Translate One To One
+   instruction.
+   Copyright (C) 1997-2009 Free Software Foundation, Inc.
+
+   Author: Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+   Based on the work by Ulrich Drepper  <drepper@cygnus.com>, 1997.
+
+   Thanks to Daniel Appich who covered the relevant performance work
+   in his diploma thesis.
+
+   This is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <dlfcn.h>
+#include <stdint.h>
+
+// conversion table from ISO-8859-1 to IBM037
+static const unsigned char table_iso8859_1_to_cp037[256]
+__attribute__ ((aligned (8))) =
+{
+  [0x0] = 0x0,[0x1] = 0x1,[0x2] = 0x2,[0x3] = 0x3,[0x4] = 0x37,[0x5] =
+  0x2D,[0x6] = 0x2E,[0x7] = 0x2F,[0x8] = 0x16,[0x9] = 0x5,[0xA] =
+  0x25,[0xB] = 0xB,[0xC] = 0xC,[0xD] = 0xD,[0xE] = 0xE,[0xF] =
+  0xF,[0x10] = 0x10,[0x11] = 0x11,[0x12] = 0x12,[0x13] = 0x13,[0x14] =
+  0x3C,[0x15] = 0x3D,[0x16] = 0x32,[0x17] = 0x26,[0x18] = 0x18,[0x19] =
+  0x19,[0x1A] = 0x3F,[0x1B] = 0x27,[0x1C] = 0x1C,[0x1D] = 0x1D,[0x1E] =
+  0x1E,[0x1F] = 0x1F,[0x20] = 0x40,[0x21] = 0x5A,[0x22] = 0x7F,[0x23] =
+  0x7B,[0x24] = 0x5B,[0x25] = 0x6C,[0x26] = 0x50,[0x27] = 0x7D,[0x28] =
+  0x4D,[0x29] = 0x5D,[0x2A] = 0x5C,[0x2B] = 0x4E,[0x2C] = 0x6B,[0x2D] =
+  0x60,[0x2E] = 0x4B,[0x2F] = 0x61,[0x30] = 0xF0,[0x31] = 0xF1,[0x32] =
+  0xF2,[0x33] = 0xF3,[0x34] = 0xF4,[0x35] = 0xF5,[0x36] = 0xF6,[0x37] =
+  0xF7,[0x38] = 0xF8,[0x39] = 0xF9,[0x3A] = 0x7A,[0x3B] = 0x5E,[0x3C] =
+  0x4C,[0x3D] = 0x7E,[0x3E] = 0x6E,[0x3F] = 0x6F,[0x40] = 0x7C,[0x41] =
+  0xC1,[0x42] = 0xC2,[0x43] = 0xC3,[0x44] = 0xC4,[0x45] = 0xC5,[0x46] =
+  0xC6,[0x47] = 0xC7,[0x48] = 0xC8,[0x49] = 0xC9,[0x4A] = 0xD1,[0x4B] =
+  0xD2,[0x4C] = 0xD3,[0x4D] = 0xD4,[0x4E] = 0xD5,[0x4F] = 0xD6,[0x50] =
+  0xD7,[0x51] = 0xD8,[0x52] = 0xD9,[0x53] = 0xE2,[0x54] = 0xE3,[0x55] =
+  0xE4,[0x56] = 0xE5,[0x57] = 0xE6,[0x58] = 0xE7,[0x59] = 0xE8,[0x5A] =
+  0xE9,[0x5B] = 0xBA,[0x5C] = 0xE0,[0x5D] = 0xBB,[0x5E] = 0xB0,[0x5F] =
+  0x6D,[0x60] = 0x79,[0x61] = 0x81,[0x62] = 0x82,[0x63] = 0x83,[0x64] =
+  0x84,[0x65] = 0x85,[0x66] = 0x86,[0x67] = 0x87,[0x68] = 0x88,[0x69] =
+  0x89,[0x6A] = 0x91,[0x6B] = 0x92,[0x6C] = 0x93,[0x6D] = 0x94,[0x6E] =
+  0x95,[0x6F] = 0x96,[0x70] = 0x97,[0x71] = 0x98,[0x72] = 0x99,[0x73] =
+  0xA2,[0x74] = 0xA3,[0x75] = 0xA4,[0x76] = 0xA5,[0x77] = 0xA6,[0x78] =
+  0xA7,[0x79] = 0xA8,[0x7A] = 0xA9,[0x7B] = 0xC0,[0x7C] = 0x4F,[0x7D] =
+  0xD0,[0x7E] = 0xA1,[0x7F] = 0x7,[0x80] = 0x20,[0x81] = 0x21,[0x82] =
+  0x22,[0x83] = 0x23,[0x84] = 0x24,[0x85] = 0x15,[0x86] = 0x6,[0x87] =
+  0x17,[0x88] = 0x28,[0x89] = 0x29,[0x8A] = 0x2A,[0x8B] = 0x2B,[0x8C] =
+  0x2C,[0x8D] = 0x9,[0x8E] = 0xA,[0x8F] = 0x1B,[0x90] = 0x30,[0x91] =
+  0x31,[0x92] = 0x1A,[0x93] = 0x33,[0x94] = 0x34,[0x95] = 0x35,[0x96] =
+  0x36,[0x97] = 0x8,[0x98] = 0x38,[0x99] = 0x39,[0x9A] = 0x3A,[0x9B] =
+  0x3B,[0x9C] = 0x4,[0x9D] = 0x14,[0x9E] = 0x3E,[0x9F] = 0xFF,[0xA0] =
+  0x41,[0xA1] = 0xAA,[0xA2] = 0x4A,[0xA3] = 0xB1,[0xA4] = 0x9F,[0xA5] =
+  0xB2,[0xA6] = 0x6A,[0xA7] = 0xB5,[0xA8] = 0xBD,[0xA9] = 0xB4,[0xAA] =
+  0x9A,[0xAB] = 0x8A,[0xAC] = 0x5F,[0xAD] = 0xCA,[0xAE] = 0xAF,[0xAF] =
+  0xBC,[0xB0] = 0x90,[0xB1] = 0x8F,[0xB2] = 0xEA,[0xB3] = 0xFA,[0xB4] =
+  0xBE,[0xB5] = 0xA0,[0xB6] = 0xB6,[0xB7] = 0xB3,[0xB8] = 0x9D,[0xB9] =
+  0xDA,[0xBA] = 0x9B,[0xBB] = 0x8B,[0xBC] = 0xB7,[0xBD] = 0xB8,[0xBE] =
+  0xB9,[0xBF] = 0xAB,[0xC0] = 0x64,[0xC1] = 0x65,[0xC2] = 0x62,[0xC3] =
+  0x66,[0xC4] = 0x63,[0xC5] = 0x67,[0xC6] = 0x9E,[0xC7] = 0x68,[0xC8] =
+  0x74,[0xC9] = 0x71,[0xCA] = 0x72,[0xCB] = 0x73,[0xCC] = 0x78,[0xCD] =
+  0x75,[0xCE] = 0x76,[0xCF] = 0x77,[0xD0] = 0xAC,[0xD1] = 0x69,[0xD2] =
+  0xED,[0xD3] = 0xEE,[0xD4] = 0xEB,[0xD5] = 0xEF,[0xD6] = 0xEC,[0xD7] =
+  0xBF,[0xD8] = 0x80,[0xD9] = 0xFD,[0xDA] = 0xFE,[0xDB] = 0xFB,[0xDC] =
+  0xFC,[0xDD] = 0xAD,[0xDE] = 0xAE,[0xDF] = 0x59,[0xE0] = 0x44,[0xE1] =
+  0x45,[0xE2] = 0x42,[0xE3] = 0x46,[0xE4] = 0x43,[0xE5] = 0x47,[0xE6] =
+  0x9C,[0xE7] = 0x48,[0xE8] = 0x54,[0xE9] = 0x51,[0xEA] = 0x52,[0xEB] =
+  0x53,[0xEC] = 0x58,[0xED] = 0x55,[0xEE] = 0x56,[0xEF] = 0x57,[0xF0] =
+  0x8C,[0xF1] = 0x49,[0xF2] = 0xCD,[0xF3] = 0xCE,[0xF4] = 0xCB,[0xF5] =
+  0xCF,[0xF6] = 0xCC,[0xF7] = 0xE1,[0xF8] = 0x70,[0xF9] = 0xDD,[0xFA] =
+  0xDE,[0xFB] = 0xDB,[0xFC] = 0xDC,[0xFD] = 0x8D,[0xFE] = 0x8E,[0xFF] =
+  0xDF};
+
+// conversion table from IBM037 to ISO-8859-1
+static const unsigned char table_cp037_iso8859_1[256]
+__attribute__ ((aligned (8))) =
+{
+  [0x0] = 0x0,[0x1] = 0x1,[0x2] = 0x2,[0x3] = 0x3,[0x4] = 0x9C,[0x5] =
+  0x9,[0x6] = 0x86,[0x7] = 0x7F,[0x8] = 0x97,[0x9] = 0x8D,[0xA] =
+  0x8E,[0xB] = 0xB,[0xC] = 0xC,[0xD] = 0xD,[0xE] = 0xE,[0xF] =
+  0xF,[0x10] = 0x10,[0x11] = 0x11,[0x12] = 0x12,[0x13] = 0x13,[0x14] =
+  0x9D,[0x15] = 0x85,[0x16] = 0x8,[0x17] = 0x87,[0x18] = 0x18,[0x19] =
+  0x19,[0x1A] = 0x92,[0x1B] = 0x8F,[0x1C] = 0x1C,[0x1D] = 0x1D,[0x1E] =
+  0x1E,[0x1F] = 0x1F,[0x20] = 0x80,[0x21] = 0x81,[0x22] = 0x82,[0x23] =
+  0x83,[0x24] = 0x84,[0x25] = 0xA,[0x26] = 0x17,[0x27] = 0x1B,[0x28] =
+  0x88,[0x29] = 0x89,[0x2A] = 0x8A,[0x2B] = 0x8B,[0x2C] = 0x8C,[0x2D] =
+  0x5,[0x2E] = 0x6,[0x2F] = 0x7,[0x30] = 0x90,[0x31] = 0x91,[0x32] =
+  0x16,[0x33] = 0x93,[0x34] = 0x94,[0x35] = 0x95,[0x36] = 0x96,[0x37] =
+  0x4,[0x38] = 0x98,[0x39] = 0x99,[0x3A] = 0x9A,[0x3B] = 0x9B,[0x3C] =
+  0x14,[0x3D] = 0x15,[0x3E] = 0x9E,[0x3F] = 0x1A,[0x40] = 0x20,[0x41] =
+  0xA0,[0x42] = 0xE2,[0x43] = 0xE4,[0x44] = 0xE0,[0x45] = 0xE1,[0x46] =
+  0xE3,[0x47] = 0xE5,[0x48] = 0xE7,[0x49] = 0xF1,[0x4A] = 0xA2,[0x4B] =
+  0x2E,[0x4C] = 0x3C,[0x4D] = 0x28,[0x4E] = 0x2B,[0x4F] = 0x7C,[0x50] =
+  0x26,[0x51] = 0xE9,[0x52] = 0xEA,[0x53] = 0xEB,[0x54] = 0xE8,[0x55] =
+  0xED,[0x56] = 0xEE,[0x57] = 0xEF,[0x58] = 0xEC,[0x59] = 0xDF,[0x5A] =
+  0x21,[0x5B] = 0x24,[0x5C] = 0x2A,[0x5D] = 0x29,[0x5E] = 0x3B,[0x5F] =
+  0xAC,[0x60] = 0x2D,[0x61] = 0x2F,[0x62] = 0xC2,[0x63] = 0xC4,[0x64] =
+  0xC0,[0x65] = 0xC1,[0x66] = 0xC3,[0x67] = 0xC5,[0x68] = 0xC7,[0x69] =
+  0xD1,[0x6A] = 0xA6,[0x6B] = 0x2C,[0x6C] = 0x25,[0x6D] = 0x5F,[0x6E] =
+  0x3E,[0x6F] = 0x3F,[0x70] = 0xF8,[0x71] = 0xC9,[0x72] = 0xCA,[0x73] =
+  0xCB,[0x74] = 0xC8,[0x75] = 0xCD,[0x76] = 0xCE,[0x77] = 0xCF,[0x78] =
+  0xCC,[0x79] = 0x60,[0x7A] = 0x3A,[0x7B] = 0x23,[0x7C] = 0x40,[0x7D] =
+  0x27,[0x7E] = 0x3D,[0x7F] = 0x22,[0x80] = 0xD8,[0x81] = 0x61,[0x82] =
+  0x62,[0x83] = 0x63,[0x84] = 0x64,[0x85] = 0x65,[0x86] = 0x66,[0x87] =
+  0x67,[0x88] = 0x68,[0x89] = 0x69,[0x8A] = 0xAB,[0x8B] = 0xBB,[0x8C] =
+  0xF0,[0x8D] = 0xFD,[0x8E] = 0xFE,[0x8F] = 0xB1,[0x90] = 0xB0,[0x91] =
+  0x6A,[0x92] = 0x6B,[0x93] = 0x6C,[0x94] = 0x6D,[0x95] = 0x6E,[0x96] =
+  0x6F,[0x97] = 0x70,[0x98] = 0x71,[0x99] = 0x72,[0x9A] = 0xAA,[0x9B] =
+  0xBA,[0x9C] = 0xE6,[0x9D] = 0xB8,[0x9E] = 0xC6,[0x9F] = 0xA4,[0xA0] =
+  0xB5,[0xA1] = 0x7E,[0xA2] = 0x73,[0xA3] = 0x74,[0xA4] = 0x75,[0xA5] =
+  0x76,[0xA6] = 0x77,[0xA7] = 0x78,[0xA8] = 0x79,[0xA9] = 0x7A,[0xAA] =
+  0xA1,[0xAB] = 0xBF,[0xAC] = 0xD0,[0xAD] = 0xDD,[0xAE] = 0xDE,[0xAF] =
+  0xAE,[0xB0] = 0x5E,[0xB1] = 0xA3,[0xB2] = 0xA5,[0xB3] = 0xB7,[0xB4] =
+  0xA9,[0xB5] = 0xA7,[0xB6] = 0xB6,[0xB7] = 0xBC,[0xB8] = 0xBD,[0xB9] =
+  0xBE,[0xBA] = 0x5B,[0xBB] = 0x5D,[0xBC] = 0xAF,[0xBD] = 0xA8,[0xBE] =
+  0xB4,[0xBF] = 0xD7,[0xC0] = 0x7B,[0xC1] = 0x41,[0xC2] = 0x42,[0xC3] =
+  0x43,[0xC4] = 0x44,[0xC5] = 0x45,[0xC6] = 0x46,[0xC7] = 0x47,[0xC8] =
+  0x48,[0xC9] = 0x49,[0xCA] = 0xAD,[0xCB] = 0xF4,[0xCC] = 0xF6,[0xCD] =
+  0xF2,[0xCE] = 0xF3,[0xCF] = 0xF5,[0xD0] = 0x7D,[0xD1] = 0x4A,[0xD2] =
+  0x4B,[0xD3] = 0x4C,[0xD4] = 0x4D,[0xD5] = 0x4E,[0xD6] = 0x4F,[0xD7] =
+  0x50,[0xD8] = 0x51,[0xD9] = 0x52,[0xDA] = 0xB9,[0xDB] = 0xFB,[0xDC] =
+  0xFC,[0xDD] = 0xF9,[0xDE] = 0xFA,[0xDF] = 0xFF,[0xE0] = 0x5C,[0xE1] =
+  0xF7,[0xE2] = 0x53,[0xE3] = 0x54,[0xE4] = 0x55,[0xE5] = 0x56,[0xE6] =
+  0x57,[0xE7] = 0x58,[0xE8] = 0x59,[0xE9] = 0x5A,[0xEA] = 0xB2,[0xEB] =
+  0xD4,[0xEC] = 0xD6,[0xED] = 0xD2,[0xEE] = 0xD3,[0xEF] = 0xD5,[0xF0] =
+  0x30,[0xF1] = 0x31,[0xF2] = 0x32,[0xF3] = 0x33,[0xF4] = 0x34,[0xF5] =
+  0x35,[0xF6] = 0x36,[0xF7] = 0x37,[0xF8] = 0x38,[0xF9] = 0x39,[0xFA] =
+  0xB3,[0xFB] = 0xDB,[0xFC] = 0xDC,[0xFD] = 0xD9,[0xFE] = 0xDA,[0xFF] =
+  0x9F,};
+
+/* Definitions used in the body of the `gconv' function.  */
+#define CHARSET_NAME		"ISO-8859-1//"
+#define FROM_LOOP		iso8859_1_to_cp037_z900
+#define TO_LOOP			cp037_to_iso8859_1_z900
+#define DEFINE_INIT		1
+#define DEFINE_FINI		1
+#define MIN_NEEDED_FROM		1
+#define MIN_NEEDED_TO		1
+
+/* The Z900 variant of troo forces us to always specify a test
+   character which ends the translation.  So if we run into the
+   situation where the translation has been interrupted due to the
+   test character we translate the character by hand and jump back
+   into the instruction.  */
+
+#define TROO_LOOP(TABLE)						\
+  {									\
+    register const unsigned char test asm ("0") = 0;			\
+    register const unsigned char *pTable asm ("1") = TABLE;		\
+    register unsigned char *pOutput asm ("2") = outptr;			\
+    register uint64_t length asm ("3");					\
+    const unsigned char* pInput = inptr;				\
+    uint64_t tmp;							\
+									\
+    length = (inend - inptr < outend - outptr ?				\
+	      inend - inptr : outend - outptr);				\
+									\
+    asm volatile ("0:                        \n\t"			\
+                  "  troo    %0,%1           \n\t"			\
+                  "  jz      1f              \n\t"			\
+                  "  jo      0b              \n\t"			\
+                  "  llgc    %3,0(%1)        \n\t"			\
+                  "  la      %3,0(%3,%4)     \n\t"			\
+                  "  mvc     0(1,%0),0(%3)   \n\t"			\
+                  "  aghi    %1,1            \n\t"			\
+                  "  aghi    %0,1            \n\t"			\
+                  "  aghi    %2,-1           \n\t"			\
+                  "  j       0b              \n\t"			\
+                  "1:                        \n"			\
+									\
+     : "+a" (pOutput), "+a" (pInput), "+d" (length), "=&a" (tmp)        \
+     : "a" (pTable), "d" (test)						\
+     : "cc");								\
+									\
+    inptr = pInput;							\
+    outptr = pOutput;							\
+  }
+
+/* First define the conversion function from ISO 8859-1 to CP037.  */
+#define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
+#define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
+#define LOOPFCT			FROM_LOOP
+#define BODY TROO_LOOP (table_iso8859_1_to_cp037)
+
+#include <iconv/loop.c>
+
+
+/* Next, define the conversion function from CP037 to ISO 8859-1.  */
+#define MIN_NEEDED_INPUT	MIN_NEEDED_TO
+#define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
+#define LOOPFCT			TO_LOOP
+#define BODY TROO_LOOP (table_cp037_iso8859_1);
+
+#include <iconv/loop.c>
+
+
+/* Now define the toplevel functions.  */
+#include <iconv/skeleton.c>
Index: libc/sysdeps/unix/sysv/linux/s390/s390-64/Implies
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/s390/s390-64/Implies
+++ libc/sysdeps/unix/sysv/linux/s390/s390-64/Implies
@@ -1 +1,2 @@
 unix/sysv/linux/wordsize-64
+s390/s390-64/iconvdata


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]