Add wasm tacle-bench targets

This commit is contained in:
2026-06-12 20:06:22 +02:00
parent 30daa8a00c
commit 08c2e9c13d
1122 changed files with 520422 additions and 0 deletions

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memcpy.c
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
Changes: no major functional changes
License: Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
*/
#include "memcpy.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
void *
sha_glibc_memcpy(void *dstpp, const void *srcpp, size_t len) {
unsigned long int dstp = (long int) dstpp;
unsigned long int srcp = (long int) srcpp;
size_t __nbytes;
/* Copy from the beginning to the end. */
/* If there not too few bytes to copy, use word copy. */
if (len >= OP_T_THRES) {
/* Copy just a few bytes to make DSTP aligned. */
len -= (-dstp) % OPSIZ;
__nbytes = (-dstp) % OPSIZ;
__pragma_loopbound(0, 0);
while (__nbytes > 0) {
BYTE __x = ((BYTE *) srcp)[0];
srcp += 1;
__nbytes -= 1;
((BYTE *) dstp)[0] = __x;
dstp += 1;
}
/* Copy whole pages from SRCP to DSTP by virtual address manipulation,
as much as possible. */
PAGE_COPY_FWD_MAYBE(dstp, srcp, len, len);
/* Copy from SRCP to DSTP taking advantage of the known alignment of
DSTP. Number of bytes remaining is put in the third argument,
i.e. in LEN. This number may vary from machine to machine. */
WORD_COPY_FWD(dstp, srcp, len, len);
/* Fall out and copy the tail. */
}
/* There are just a few bytes to copy. Use byte memory operations. */
__nbytes = len;
__pragma_loopbound(0, 7);
while (__nbytes > 0) {
BYTE __x = ((BYTE *) srcp)[0];
srcp += 1;
__nbytes -= 1;
((BYTE *) dstp)[0] = __x;
dstp += 1;
}
return dstpp;
}

View File

@ -0,0 +1,25 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memcpy.c
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
Changes: no major functional changes
License: Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
*/
#include "memhelper.h"
#include "sha.h"
void *sha_glibc_memcpy(void *dstpp, const void *srcpp, size_t len);

View File

@ -0,0 +1,151 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memhelper.c
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy block beginning at SRCP to
block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
Both SRCP and DSTP should be aligned for memory operations on `op_t's.
Source: GNU C Library
Changes: no major functional changes
License: Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
*/
#include "memhelper.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int printf(const char *restrict format, ...);
/* sha_wordcopy_fwd_aligned -- Copy block beginning at SRCP to
block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
Both SRCP and DSTP should be aligned for memory operations on `op_t's.
*/
void
sha_wordcopy_fwd_aligned(long int dstp, long int srcp, size_t len) {
op_t a0 = 0;
op_t a1 = 0;
char switch_target;
switch (len % 8) {
case 2:
a0 = ((op_t *) srcp)[0];
srcp -= 6 * OPSIZ;
dstp -= 7 * OPSIZ;
len += 6;
switch_target = 1;
break;
case 3:
a1 = ((op_t *) srcp)[0];
srcp -= 5 * OPSIZ;
dstp -= 6 * OPSIZ;
len += 5;
switch_target = 2;
break;
case 4:
a0 = ((op_t *) srcp)[0];
srcp -= 4 * OPSIZ;
dstp -= 5 * OPSIZ;
len += 4;
switch_target = 3;
break;
case 5:
a1 = ((op_t *) srcp)[0];
srcp -= 3 * OPSIZ;
dstp -= 4 * OPSIZ;
len += 3;
switch_target = 4;
break;
case 6:
a0 = ((op_t *) srcp)[0];
srcp -= 2 * OPSIZ;
dstp -= 3 * OPSIZ;
len += 2;
switch_target = 5;
break;
case 7:
a1 = ((op_t *) srcp)[0];
srcp -= 1 * OPSIZ;
dstp -= 2 * OPSIZ;
len += 1;
switch_target = 6;
break;
case 0:
if (OP_T_THRES <= 3 * OPSIZ && len == 0)
return;
a0 = ((op_t *) srcp)[0];
srcp -= 0 * OPSIZ;
dstp -= 1 * OPSIZ;
switch_target = 7;
break;
case 1:
a1 = ((op_t *) srcp)[0];
srcp -= -1 * OPSIZ;
dstp -= 0 * OPSIZ;
len -= 1;
if (OP_T_THRES <= 3 * OPSIZ && len == 0) {
((op_t *) dstp)[0] = a1;
return;
} else {
switch_target = 8;
break;
}
}
__pragma_loopbound(1, 2); // max 1
do {
switch (switch_target) {
case 8:
a0 = ((op_t *) srcp)[0];
((op_t *) dstp)[0] = a1;
break;
case 7:
a1 = ((op_t *) srcp)[1];
((op_t *) dstp)[1] = a0;
break;
case 6:
a0 = ((op_t *) srcp)[2];
((op_t *) dstp)[2] = a1;
break;
case 5:
a1 = ((op_t *) srcp)[3];
((op_t *) dstp)[3] = a0;
break;
case 4:
a0 = ((op_t *) srcp)[4];
((op_t *) dstp)[4] = a1;
break;
case 3:
a1 = ((op_t *) srcp)[5];
((op_t *) dstp)[5] = a0;
break;
case 2:
a0 = ((op_t *) srcp)[6];
((op_t *) dstp)[6] = a1;
break;
case 1:
a1 = ((op_t *) srcp)[7];
((op_t *) dstp)[7] = a0;
break;
}
srcp += 8 * OPSIZ;
dstp += 8 * OPSIZ;
len -= 8;
switch_target = 8;
} while (len != 0);
((op_t *) dstp)[0] = a1;
}

View File

@ -0,0 +1,54 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memhelper.h
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
NIST Secure Hash Algorithm
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
Bruce Schneier
License: GNU Lesser General Public License
Changes: no major functional changes
*/
#ifndef MEM_HELPER_H
#define MEM_HELPER_H
#include "sha.h"
void sha_wordcopy_fwd_aligned(long int dstp, long int srcp, size_t len);
/* Type to use for aligned memory operations.
This should normally be the biggest type supported by a single load
and store. */
#define op_t unsigned long int
#define OPSIZ (sizeof(op_t))
/* Threshold value for when to enter the unrolled loops. */
#define OP_T_THRES 16
#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes)
#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with
the assumption that DST_BP is aligned on an OPSIZ multiple. If
not all bytes could be easily copied, store remaining number of bytes
in NBYTES_LEFT, otherwise store 0. */
#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \
{ \
if (src_bp % OPSIZ == 0) \
sha_wordcopy_fwd_aligned(dst_bp, src_bp, (nbytes) / OPSIZ); \
else \
src_bp += (nbytes) & -OPSIZ; \
dst_bp += (nbytes) & -OPSIZ; \
(nbytes_left) = (nbytes) % OPSIZ; \
}
#endif // MEM_HELPER_H

View File

@ -0,0 +1,92 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: menset.h
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
Changes: no major functional changes
License: GNU Lesser General Public License
*/
#include "memset.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int printf(const char *restrict format, ...);
void *
sha_glibc_memset(void *dstpp, int c, size_t len) {
long int dstp = (long int) dstpp;
if (len >= 8) {
size_t xlen;
op_t cccc;
cccc = (unsigned char) c;
cccc |= cccc << 8;
cccc |= cccc << 16;
if (OPSIZ > 4)
/* Do the shift in two steps to avoid warning if long has 32 bits.
*/
cccc |= (cccc << 16) << 16;
/* There are at least some bytes to set.
No need to test for LEN == 0 in this alignment loop. */
__pragma_loopbound(3, 3);
while (dstp % OPSIZ != 0) {
((BYTE *) dstp)[0] = c;
dstp += 1;
len -= 1;
}
/* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
xlen = len / (OPSIZ * 8);
__pragma_loopbound(0, 1);
while (xlen > 0) {
((op_t *) dstp)[0] = cccc;
((op_t *) dstp)[1] = cccc;
((op_t *) dstp)[2] = cccc;
((op_t *) dstp)[3] = cccc;
((op_t *) dstp)[4] = cccc;
((op_t *) dstp)[5] = cccc;
((op_t *) dstp)[6] = cccc;
((op_t *) dstp)[7] = cccc;
dstp += 8 * OPSIZ;
xlen -= 1;
}
len %= OPSIZ * 8;
/* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
xlen = len / OPSIZ;
__pragma_loopbound(1, 2);
while (xlen > 0) {
((op_t *) dstp)[0] = cccc;
dstp += OPSIZ;
xlen -= 1;
}
len %= OPSIZ;
}
/* Write the last few bytes. */
__pragma_loopbound(0, 0);
while (len > 0) {
((BYTE *) dstp)[0] = c;
dstp += 1;
len -= 1;
}
return (void *) dstpp;
}

View File

@ -0,0 +1,23 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: menset.h
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
License: GNU Lesser General Public License
Changes: no major functional changes
*/
#include "memhelper.h"
void *sha_glibc_memset(void *dstpp, int c, size_t len);

View File

@ -0,0 +1,232 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: sha.c
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
NIST Secure Hash Algorithm
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
Bruce Schneier
Changes: no major functional changes
License: GNU Lesser General Public License
*/
#include "sha.h"
#include "memcpy.h"
#include "memset.h"
/*
Declaration of global variables
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
struct SHA_INFO sha_info;
/* SHA f()-functions */
#define f1(x, y, z) ((x & y) | (~x & z))
#define f2(x, y, z) (x ^ y ^ z)
#define f3(x, y, z) ((x & y) | (x & z) | (y & z))
#define f4(x, y, z) (x ^ y ^ z)
/* SHA constants */
#define CONST1 0x5a827999L
#define CONST2 0x6ed9eba1L
#define CONST3 0x8f1bbcdcL
#define CONST4 0xca62c1d6L
#define BLOCK_SIZE 8192
/* 32-bit rotate */
#define ROT32(x, n) ((x << n) | (x >> (32 - n)))
#define FUNC(n, i) \
temp = ROT32(A, 5) + f##n(B, C, D) + E + W[i] + CONST##n; \
E = D; \
D = C; \
C = ROT32(B, 30); \
B = A; \
A = temp
/* do SHA transformation */
void
sha_transform(struct SHA_INFO *sha_info) {
int i;
LONG temp, A, B, C, D, E, W[80];
__pragma_loopbound(16, 16);
for (i = 0; i < 16; ++i)
W[i] = sha_info->data[i];
__pragma_loopbound(64, 64);
for (i = 16; i < 80; ++i)
W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
A = sha_info->digest[0];
B = sha_info->digest[1];
C = sha_info->digest[2];
D = sha_info->digest[3];
E = sha_info->digest[4];
__pragma_loopbound(20, 20);
for (i = 0; i < 20; ++i) {
FUNC(1, i);
}
__pragma_loopbound(20, 20);
for (i = 20; i < 40; ++i) {
FUNC(2, i);
}
__pragma_loopbound(20, 20);
for (i = 40; i < 60; ++i) {
FUNC(3, i);
}
__pragma_loopbound(20, 20);
for (i = 60; i < 80; ++i) {
FUNC(4, i);
}
sha_info->digest[0] += A;
sha_info->digest[1] += B;
sha_info->digest[2] += C;
sha_info->digest[3] += D;
sha_info->digest[4] += E;
}
/* change endianness of data */
void
sha_byte_reverse(LONG *buffer, int count) {
int i;
BYTE ct[4], *cp;
count /= sizeof(LONG);
cp = (BYTE *) buffer;
__pragma_loopbound(16, 16);
for (i = 0; i < count; ++i) {
ct[0] = cp[0];
ct[1] = cp[1];
ct[2] = cp[2];
ct[3] = cp[3];
cp[0] = ct[3];
cp[1] = ct[2];
cp[2] = ct[1];
cp[3] = ct[0];
cp += sizeof(LONG);
}
}
/* initialize the SHA digest */
void
sha_init(void) {
int i;
sha_info.digest[0] = 0x67452301L;
sha_info.digest[1] = 0xefcdab89L;
sha_info.digest[2] = 0x98badcfeL;
sha_info.digest[3] = 0x10325476L;
sha_info.digest[4] = 0xc3d2e1f0L;
sha_info.count_lo = 0L;
sha_info.count_hi = 0L;
for (i = 0; i < 16; i++)
sha_info.data[i] = 0;
}
size_t
sha_fread(void *ptr, size_t size, size_t count, struct SHA_MY_FILE *stream) {
unsigned i = stream->cur_pos, i2 = 0;
size_t number_of_chars_to_read =
stream->size - stream->cur_pos >= size * count
? size * count
: stream->size - stream->cur_pos;
__pragma_loopbound(0, 8192);
while (i < stream->cur_pos + number_of_chars_to_read)
((unsigned char *) ptr)[i2++] = stream->data[i++];
stream->cur_pos += number_of_chars_to_read;
return (number_of_chars_to_read);
}
/* update the SHA digest */
void
sha_update(struct SHA_INFO *sha_info, BYTE *buffer, int count) {
if ((sha_info->count_lo + ((LONG) count << 3)) < sha_info->count_lo)
++sha_info->count_hi;
sha_info->count_lo += (LONG) count << 3;
sha_info->count_hi += (LONG) count >> 29;
__pragma_loopbound(8, 128);
while (count >= SHA_BLOCKSIZE) {
sha_glibc_memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
sha_transform(sha_info);
buffer += SHA_BLOCKSIZE;
count -= SHA_BLOCKSIZE;
}
sha_glibc_memcpy(sha_info->data, buffer, count);
}
/* finish computing the SHA digest */
void
sha_final(struct SHA_INFO *sha_info) {
int count;
LONG lo_bit_count, hi_bit_count;
lo_bit_count = sha_info->count_lo;
hi_bit_count = sha_info->count_hi;
count = (int) ((lo_bit_count >> 3) & 0x3f);
((BYTE *) sha_info->data)[count++] = 0x80;
if (count > 56) {
sha_glibc_memset((BYTE *) &sha_info->data + count, 0, 64 - count);
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
sha_transform(sha_info);
sha_glibc_memset(&sha_info->data, 0, 56);
} else
sha_glibc_memset((BYTE *) &sha_info->data + count, 0, 56 - count);
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
sha_info->data[14] = hi_bit_count;
sha_info->data[15] = lo_bit_count;
sha_transform(sha_info);
}
/* compute the SHA digest of a FILE stream */
void
sha_stream(struct SHA_INFO *sha_info, struct SHA_MY_FILE *fin) {
int i;
BYTE data[BLOCK_SIZE];
__pragma_loopbound(5, 5);
while ((i = sha_fread(data, 1, BLOCK_SIZE, fin)) > 0)
sha_update(sha_info, data, i);
sha_final(sha_info);
}
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
sha_main(void) {
struct SHA_MY_FILE fin;
fin.data = sha_data;
fin.size = 32743; // set size = 3247552 for input_large
fin.cur_pos = 0;
sha_stream(&sha_info, &fin);
}
int
sha_return(void) {
int sum = 0;
sum = sha_info.data[14] + sha_info.data[15];
return (sum - 261944 != 0);
}
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
sha_init();
sha_main();
return (sha_return());
}

View File

@ -0,0 +1,64 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: sha.h
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
NIST Secure Hash Algorithm
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
Bruce Schneier
Changes: no major functional changes
License: May be used, modified, and re-distributed freely.
*/
#ifndef SHA_H
#define SHA_H
/* Useful defines & typedefs */
typedef unsigned char BYTE;
typedef unsigned long LONG;
typedef unsigned size_t;
/* Type to use for unaligned operations. */
#define SHA_BLOCKSIZE 64
#define SHA_DIGESTSIZE 20
#define LITTLE_ENDIAN
#define NULL ((void *) 0)
extern unsigned volatile char sha_data[32743];
struct SHA_MY_FILE {
unsigned volatile char *data;
size_t size;
unsigned cur_pos;
};
struct SHA_INFO {
LONG digest[5]; /* message digest */
LONG count_lo, count_hi; /* 64-bit bit count */
LONG data[16]; /* SHA data buffer */
};
/*
Forward declaration of functions
*/
void sha_transform(struct SHA_INFO *);
void sha_byte_reverse(LONG *buffer, int count);
void sha_init(void);
size_t sha_fread(void *, size_t, size_t, struct SHA_MY_FILE *);
void sha_update(struct SHA_INFO *, BYTE *, int);
void sha_final(struct SHA_INFO *);
void sha_stream(struct SHA_INFO *, struct SHA_MY_FILE *);
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
sha_main(void);
int sha_return(void);
__attribute__((noinline)) __attribute__((export_name("main"))) int main(void);
#endif // SHA_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memcpy.c
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
Changes: no major functional changes
License: Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
*/
#include "memcpy.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline void *
sha_glibc_memcpy(void *dstpp, const void *srcpp, size_t len) {
unsigned long int dstp = (long int) dstpp;
unsigned long int srcp = (long int) srcpp;
size_t __nbytes;
/* Copy from the beginning to the end. */
/* If there not too few bytes to copy, use word copy. */
if (len >= OP_T_THRES) {
/* Copy just a few bytes to make DSTP aligned. */
len -= (-dstp) % OPSIZ;
__nbytes = (-dstp) % OPSIZ;
__pragma_loopbound(0, 0);
while (__nbytes > 0) {
BYTE __x = ((BYTE *) srcp)[0];
srcp += 1;
__nbytes -= 1;
((BYTE *) dstp)[0] = __x;
dstp += 1;
}
/* Copy whole pages from SRCP to DSTP by virtual address manipulation,
as much as possible. */
PAGE_COPY_FWD_MAYBE(dstp, srcp, len, len);
/* Copy from SRCP to DSTP taking advantage of the known alignment of
DSTP. Number of bytes remaining is put in the third argument,
i.e. in LEN. This number may vary from machine to machine. */
WORD_COPY_FWD(dstp, srcp, len, len);
/* Fall out and copy the tail. */
}
/* There are just a few bytes to copy. Use byte memory operations. */
__nbytes = len;
__pragma_loopbound(0, 7);
while (__nbytes > 0) {
BYTE __x = ((BYTE *) srcp)[0];
srcp += 1;
__nbytes -= 1;
((BYTE *) dstp)[0] = __x;
dstp += 1;
}
return dstpp;
}

View File

@ -0,0 +1,26 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memcpy.c
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
Changes: no major functional changes
License: Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
*/
#include "memhelper.h"
#include "sha.h"
__attribute__((always_inline)) static inline void *
sha_glibc_memcpy(void *dstpp, const void *srcpp, size_t len);

View File

@ -0,0 +1,151 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memhelper.c
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy block beginning at SRCP to
block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
Both SRCP and DSTP should be aligned for memory operations on `op_t's.
Source: GNU C Library
Changes: no major functional changes
License: Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
*/
#include "memhelper.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int printf(const char *restrict format, ...);
/* sha_wordcopy_fwd_aligned -- Copy block beginning at SRCP to
block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
Both SRCP and DSTP should be aligned for memory operations on `op_t's.
*/
__attribute__((always_inline)) static inline void
sha_wordcopy_fwd_aligned(long int dstp, long int srcp, size_t len) {
op_t a0 = 0;
op_t a1 = 0;
char switch_target;
switch (len % 8) {
case 2:
a0 = ((op_t *) srcp)[0];
srcp -= 6 * OPSIZ;
dstp -= 7 * OPSIZ;
len += 6;
switch_target = 1;
break;
case 3:
a1 = ((op_t *) srcp)[0];
srcp -= 5 * OPSIZ;
dstp -= 6 * OPSIZ;
len += 5;
switch_target = 2;
break;
case 4:
a0 = ((op_t *) srcp)[0];
srcp -= 4 * OPSIZ;
dstp -= 5 * OPSIZ;
len += 4;
switch_target = 3;
break;
case 5:
a1 = ((op_t *) srcp)[0];
srcp -= 3 * OPSIZ;
dstp -= 4 * OPSIZ;
len += 3;
switch_target = 4;
break;
case 6:
a0 = ((op_t *) srcp)[0];
srcp -= 2 * OPSIZ;
dstp -= 3 * OPSIZ;
len += 2;
switch_target = 5;
break;
case 7:
a1 = ((op_t *) srcp)[0];
srcp -= 1 * OPSIZ;
dstp -= 2 * OPSIZ;
len += 1;
switch_target = 6;
break;
case 0:
if (OP_T_THRES <= 3 * OPSIZ && len == 0)
return;
a0 = ((op_t *) srcp)[0];
srcp -= 0 * OPSIZ;
dstp -= 1 * OPSIZ;
switch_target = 7;
break;
case 1:
a1 = ((op_t *) srcp)[0];
srcp -= -1 * OPSIZ;
dstp -= 0 * OPSIZ;
len -= 1;
if (OP_T_THRES <= 3 * OPSIZ && len == 0) {
((op_t *) dstp)[0] = a1;
return;
} else {
switch_target = 8;
break;
}
}
__pragma_loopbound(1, 2); // max 1
do {
switch (switch_target) {
case 8:
a0 = ((op_t *) srcp)[0];
((op_t *) dstp)[0] = a1;
break;
case 7:
a1 = ((op_t *) srcp)[1];
((op_t *) dstp)[1] = a0;
break;
case 6:
a0 = ((op_t *) srcp)[2];
((op_t *) dstp)[2] = a1;
break;
case 5:
a1 = ((op_t *) srcp)[3];
((op_t *) dstp)[3] = a0;
break;
case 4:
a0 = ((op_t *) srcp)[4];
((op_t *) dstp)[4] = a1;
break;
case 3:
a1 = ((op_t *) srcp)[5];
((op_t *) dstp)[5] = a0;
break;
case 2:
a0 = ((op_t *) srcp)[6];
((op_t *) dstp)[6] = a1;
break;
case 1:
a1 = ((op_t *) srcp)[7];
((op_t *) dstp)[7] = a0;
break;
}
srcp += 8 * OPSIZ;
dstp += 8 * OPSIZ;
len -= 8;
switch_target = 8;
} while (len != 0);
((op_t *) dstp)[0] = a1;
}

View File

@ -0,0 +1,55 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: memhelper.h
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
NIST Secure Hash Algorithm
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
Bruce Schneier
License: GNU Lesser General Public License
Changes: no major functional changes
*/
#ifndef MEM_HELPER_H
#define MEM_HELPER_H
#include "sha.h"
__attribute__((always_inline)) static inline void
sha_wordcopy_fwd_aligned(long int dstp, long int srcp, size_t len);
/* Type to use for aligned memory operations.
This should normally be the biggest type supported by a single load
and store. */
#define op_t unsigned long int
#define OPSIZ (sizeof(op_t))
/* Threshold value for when to enter the unrolled loops. */
#define OP_T_THRES 16
#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes)
#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with
the assumption that DST_BP is aligned on an OPSIZ multiple. If
not all bytes could be easily copied, store remaining number of bytes
in NBYTES_LEFT, otherwise store 0. */
#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \
{ \
if (src_bp % OPSIZ == 0) \
sha_wordcopy_fwd_aligned(dst_bp, src_bp, (nbytes) / OPSIZ); \
else \
src_bp += (nbytes) & -OPSIZ; \
dst_bp += (nbytes) & -OPSIZ; \
(nbytes_left) = (nbytes) % OPSIZ; \
}
#endif // MEM_HELPER_H

View File

@ -0,0 +1,92 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: menset.h
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
Changes: no major functional changes
License: GNU Lesser General Public License
*/
#include "memset.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int printf(const char *restrict format, ...);
__attribute__((always_inline)) static inline void *
sha_glibc_memset(void *dstpp, int c, size_t len) {
long int dstp = (long int) dstpp;
if (len >= 8) {
size_t xlen;
op_t cccc;
cccc = (unsigned char) c;
cccc |= cccc << 8;
cccc |= cccc << 16;
if (OPSIZ > 4)
/* Do the shift in two steps to avoid warning if long has 32 bits.
*/
cccc |= (cccc << 16) << 16;
/* There are at least some bytes to set.
No need to test for LEN == 0 in this alignment loop. */
__pragma_loopbound(3, 3);
while (dstp % OPSIZ != 0) {
((BYTE *) dstp)[0] = c;
dstp += 1;
len -= 1;
}
/* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
xlen = len / (OPSIZ * 8);
__pragma_loopbound(0, 1);
while (xlen > 0) {
((op_t *) dstp)[0] = cccc;
((op_t *) dstp)[1] = cccc;
((op_t *) dstp)[2] = cccc;
((op_t *) dstp)[3] = cccc;
((op_t *) dstp)[4] = cccc;
((op_t *) dstp)[5] = cccc;
((op_t *) dstp)[6] = cccc;
((op_t *) dstp)[7] = cccc;
dstp += 8 * OPSIZ;
xlen -= 1;
}
len %= OPSIZ * 8;
/* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
xlen = len / OPSIZ;
__pragma_loopbound(1, 2);
while (xlen > 0) {
((op_t *) dstp)[0] = cccc;
dstp += OPSIZ;
xlen -= 1;
}
len %= OPSIZ;
}
/* Write the last few bytes. */
__pragma_loopbound(0, 0);
while (len > 0) {
((BYTE *) dstp)[0] = c;
dstp += 1;
len -= 1;
}
return (void *) dstpp;
}

View File

@ -0,0 +1,24 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: menset.h
Author: Torbjorn Granlund
NIST Secure Hash Algorithm
Copy memory to memory until the specified number of bytes
has been copied. Overlap is NOT handled correctly.
Source: GNU C Library
License: GNU Lesser General Public License
Changes: no major functional changes
*/
#include "memhelper.h"
__attribute__((always_inline)) static inline void *
sha_glibc_memset(void *dstpp, int c, size_t len);

View File

@ -0,0 +1,241 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: sha.c
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
NIST Secure Hash Algorithm
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
Bruce Schneier
Changes: no major functional changes
License: GNU Lesser General Public License
*/
#include "sha.h"
#include "memcpy.h"
#include "memset.h"
/*
Declaration of global variables
*/
// Wasm loop bounds
#include "input_small.c"
#include "memcpy.c"
#include "memhelper.c"
#include "memset.c"
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
struct SHA_INFO sha_info;
/* SHA f()-functions */
#define f1(x, y, z) ((x & y) | (~x & z))
#define f2(x, y, z) (x ^ y ^ z)
#define f3(x, y, z) ((x & y) | (x & z) | (y & z))
#define f4(x, y, z) (x ^ y ^ z)
/* SHA constants */
#define CONST1 0x5a827999L
#define CONST2 0x6ed9eba1L
#define CONST3 0x8f1bbcdcL
#define CONST4 0xca62c1d6L
#define BLOCK_SIZE 8192
/* 32-bit rotate */
#define ROT32(x, n) ((x << n) | (x >> (32 - n)))
#define FUNC(n, i) \
temp = ROT32(A, 5) + f##n(B, C, D) + E + W[i] + CONST##n; \
E = D; \
D = C; \
C = ROT32(B, 30); \
B = A; \
A = temp
/* do SHA transformation */
__attribute__((always_inline)) static inline void
sha_transform(struct SHA_INFO *sha_info) {
int i;
LONG temp, A, B, C, D, E, W[80];
__pragma_loopbound(16, 16);
for (i = 0; i < 16; ++i)
W[i] = sha_info->data[i];
__pragma_loopbound(64, 64);
for (i = 16; i < 80; ++i)
W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
A = sha_info->digest[0];
B = sha_info->digest[1];
C = sha_info->digest[2];
D = sha_info->digest[3];
E = sha_info->digest[4];
__pragma_loopbound(20, 20);
for (i = 0; i < 20; ++i) {
FUNC(1, i);
}
__pragma_loopbound(20, 20);
for (i = 20; i < 40; ++i) {
FUNC(2, i);
}
__pragma_loopbound(20, 20);
for (i = 40; i < 60; ++i) {
FUNC(3, i);
}
__pragma_loopbound(20, 20);
for (i = 60; i < 80; ++i) {
FUNC(4, i);
}
sha_info->digest[0] += A;
sha_info->digest[1] += B;
sha_info->digest[2] += C;
sha_info->digest[3] += D;
sha_info->digest[4] += E;
}
/* change endianness of data */
__attribute__((always_inline)) static inline void
sha_byte_reverse(LONG *buffer, int count) {
int i;
BYTE ct[4], *cp;
count /= sizeof(LONG);
cp = (BYTE *) buffer;
__pragma_loopbound(16, 16);
for (i = 0; i < count; ++i) {
ct[0] = cp[0];
ct[1] = cp[1];
ct[2] = cp[2];
ct[3] = cp[3];
cp[0] = ct[3];
cp[1] = ct[2];
cp[2] = ct[1];
cp[3] = ct[0];
cp += sizeof(LONG);
}
}
/* initialize the SHA digest */
__attribute__((always_inline)) static inline void
sha_init(void) {
int i;
sha_info.digest[0] = 0x67452301L;
sha_info.digest[1] = 0xefcdab89L;
sha_info.digest[2] = 0x98badcfeL;
sha_info.digest[3] = 0x10325476L;
sha_info.digest[4] = 0xc3d2e1f0L;
sha_info.count_lo = 0L;
sha_info.count_hi = 0L;
for (i = 0; i < 16; i++)
sha_info.data[i] = 0;
}
__attribute__((always_inline)) static inline size_t
sha_fread(void *ptr, size_t size, size_t count, struct SHA_MY_FILE *stream) {
unsigned i = stream->cur_pos, i2 = 0;
size_t number_of_chars_to_read =
stream->size - stream->cur_pos >= size * count
? size * count
: stream->size - stream->cur_pos;
__pragma_loopbound(0, 8192);
while (i < stream->cur_pos + number_of_chars_to_read)
((unsigned char *) ptr)[i2++] = stream->data[i++];
stream->cur_pos += number_of_chars_to_read;
return (number_of_chars_to_read);
}
/* update the SHA digest */
__attribute__((always_inline)) static inline void
sha_update(struct SHA_INFO *sha_info, BYTE *buffer, int count) {
if ((sha_info->count_lo + ((LONG) count << 3)) < sha_info->count_lo)
++sha_info->count_hi;
sha_info->count_lo += (LONG) count << 3;
sha_info->count_hi += (LONG) count >> 29;
__pragma_loopbound(8, 128);
while (count >= SHA_BLOCKSIZE) {
sha_glibc_memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
sha_transform(sha_info);
buffer += SHA_BLOCKSIZE;
count -= SHA_BLOCKSIZE;
}
sha_glibc_memcpy(sha_info->data, buffer, count);
}
/* finish computing the SHA digest */
__attribute__((always_inline)) static inline void
sha_final(struct SHA_INFO *sha_info) {
int count;
LONG lo_bit_count, hi_bit_count;
lo_bit_count = sha_info->count_lo;
hi_bit_count = sha_info->count_hi;
count = (int) ((lo_bit_count >> 3) & 0x3f);
((BYTE *) sha_info->data)[count++] = 0x80;
if (count > 56) {
sha_glibc_memset((BYTE *) &sha_info->data + count, 0, 64 - count);
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
sha_transform(sha_info);
sha_glibc_memset(&sha_info->data, 0, 56);
} else
sha_glibc_memset((BYTE *) &sha_info->data + count, 0, 56 - count);
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
sha_info->data[14] = hi_bit_count;
sha_info->data[15] = lo_bit_count;
sha_transform(sha_info);
}
/* compute the SHA digest of a FILE stream */
__attribute__((always_inline)) static inline void
sha_stream(struct SHA_INFO *sha_info, struct SHA_MY_FILE *fin) {
int i;
BYTE data[BLOCK_SIZE];
__pragma_loopbound(5, 5);
while ((i = sha_fread(data, 1, BLOCK_SIZE, fin)) > 0)
sha_update(sha_info, data, i);
sha_final(sha_info);
}
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
sha_main(void) {
struct SHA_MY_FILE fin;
fin.data = sha_data;
fin.size = 32743; // set size = 3247552 for input_large
fin.cur_pos = 0;
sha_stream(&sha_info, &fin);
}
__attribute__((always_inline)) static inline int
sha_return(void) {
int sum = 0;
sum = sha_info.data[14] + sha_info.data[15];
return (sum - 261944 != 0);
}
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
sha_init();
sha_main();
return (sha_return());
}

View File

@ -0,0 +1,72 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: sha.h
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
NIST Secure Hash Algorithm
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
Bruce Schneier
Changes: no major functional changes
License: May be used, modified, and re-distributed freely.
*/
#ifndef SHA_H
#define SHA_H
/* Useful defines & typedefs */
typedef unsigned char BYTE;
typedef unsigned long LONG;
typedef unsigned size_t;
/* Type to use for unaligned operations. */
#define SHA_BLOCKSIZE 64
#define SHA_DIGESTSIZE 20
#define LITTLE_ENDIAN
#define NULL ((void *) 0)
extern unsigned volatile char sha_data[32743];
struct SHA_MY_FILE {
unsigned volatile char *data;
size_t size;
unsigned cur_pos;
};
struct SHA_INFO {
LONG digest[5]; /* message digest */
LONG count_lo, count_hi; /* 64-bit bit count */
LONG data[16]; /* SHA data buffer */
};
/*
Forward declaration of functions
*/
__attribute__((always_inline)) static inline void
sha_transform(struct SHA_INFO *);
__attribute__((always_inline)) static inline void sha_byte_reverse(LONG *buffer,
int count);
__attribute__((always_inline)) static inline void sha_init(void);
__attribute__((always_inline)) static inline size_t
sha_fread(void *, size_t, size_t, struct SHA_MY_FILE *);
__attribute__((always_inline)) static inline void sha_update(struct SHA_INFO *,
BYTE *, int);
__attribute__((always_inline)) static inline void sha_final(struct SHA_INFO *);
__attribute__((always_inline)) static inline void
sha_stream(struct SHA_INFO *, struct SHA_MY_FILE *);
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
sha_main(void);
__attribute__((always_inline)) static inline int sha_return(void);
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void);
#endif // SHA_H