Add wasm tacle-bench targets
This commit is contained in:
28
targets/wasm-tacle/sequential/ammunition/CMakeLists.txt
Normal file
28
targets/wasm-tacle/sequential/ammunition/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
# ~~~
|
||||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
|
||||
# ~~~
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(ammunition)
|
||||
|
||||
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
|
||||
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
|
||||
|
||||
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
|
||||
|
||||
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
|
||||
set(APP_SOURCE_FILE_PATH
|
||||
"generated/modified_sources/inline/ammunition.c")
|
||||
else()
|
||||
set(APP_SOURCE_FILE_PATH
|
||||
"generated/modified_sources/default/ammunition.c"
|
||||
"generated/modified_sources/default/ammunition_libc.c"
|
||||
"generated/modified_sources/default/arithm.c"
|
||||
"generated/modified_sources/default/bits.c")
|
||||
endif()
|
||||
|
||||
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)
|
||||
|
||||
|
||||
66
targets/wasm-tacle/sequential/ammunition/ChangeLog.txt
Executable file
66
targets/wasm-tacle/sequential/ammunition/ChangeLog.txt
Executable file
@ -0,0 +1,66 @@
|
||||
File: ammunition.c
|
||||
Original provenience: DINO programming language
|
||||
|
||||
2016-03-03:
|
||||
- Add generic TACLeBench header
|
||||
- Prefix global functions with benchmark name
|
||||
- Introduce volatile result variable for return statements
|
||||
- Split code into ammunition_init and ammunition_main
|
||||
- Fix compiler warnings "array subscript is of type 'char'":
|
||||
char => unsigned char
|
||||
- Fix compiler warnings "'&&' within '||'":
|
||||
Place additional parentheses
|
||||
- Remove usages and comments related to the macros
|
||||
HAVE_MEMMOVE, NDEBUG, HAVE_MEMCMP
|
||||
- Remove comment related to unused NO_TEMPLATE macro
|
||||
2016-05-02:
|
||||
- Change C++ style comments to ISO C90 compliant comments
|
||||
- Avoid mixing declarations and code: move declaration of variable writePos in
|
||||
functions ammunition_sprintf_d and ammunition_sprintf_u
|
||||
- Change datatype in function ammunition_bits_test of iteration variables i and
|
||||
j from int to unsigned int to avoid comparison between signed and unsigned
|
||||
integer expressions
|
||||
- Add forward declarations to ammunition.c
|
||||
- Introduce variable ammunition_result
|
||||
- Parantheses around comparison in functions ammunition_isdigit and
|
||||
ammunition_isspace
|
||||
- Remove usage of limits.h, move definitions of limits into separate file
|
||||
ammunition_limits.h
|
||||
- Remove unconditional assignments of variable result to zero after each test in
|
||||
functions ammunition_bits_test and ammunition_arithm_test
|
||||
- Remove unused functions unsigned_integer_maximum, integer_minimum,
|
||||
integer_maximum, integer_remainder
|
||||
- Remove unused declaration of function default_arithmetic_overflow_reaction
|
||||
- Remove unused variables zero_constant_itself, zero_constant
|
||||
- Remove unused declarations of functions set_unsigned_integer_overflow_reaction
|
||||
and set_integer_overflow_reaction
|
||||
- Remove block #ifndef MAX_INTEGER_OPERAND_SIZE, set definition of
|
||||
MAX_INTEGER_OPERAND_SIZE to 128, since this is default
|
||||
2016-05-10:
|
||||
- Integrate new version of arithm library from ammunition repository from
|
||||
dino repository on github (commit: db9cfab042c332abb234ec8d72750103010981c1),
|
||||
which hanles arithmetic shifts by negative numbers. This change now makes all
|
||||
test cases in ammunition.c pass. Update headers unsigned int bits => int bits
|
||||
- Remove assert statements
|
||||
- Fix memcmp implementation: dereferencing pointer was missing
|
||||
- Add loop-bound annotation to memcmp
|
||||
- Fix strcmp implementation
|
||||
- Integrate working versions of memcpy and memset from pm benchmark
|
||||
- Update signature of ammunition_memcpy to original version:
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
- Move functions from libc into separate file, introduce header files
|
||||
ammunition_limits.h, ammunition_stdio.h, ammunition_stdlib.h,
|
||||
ammunition_string.h
|
||||
- Fix overflow in sprintf_d: change datatype of variable 'copyOfNumber' from int
|
||||
to long, since the negative value of INT_MIN is undefined
|
||||
2016-05-17:
|
||||
- Remove all static declarations of global functions
|
||||
- Rename variables 'digit_number' to digit_num to keep lines below 80 characters
|
||||
- Rename op1_digit_number to op1_digit_number and op1_digit_num in function
|
||||
'ammunition_multiply_unsigned_integer_without_overflow_reaction'
|
||||
- Rename variable 'scaled_op1_digit_number' in function
|
||||
'ammunition_divide_unsigned_integer_without_overflow_reaction'
|
||||
- Apply code formatting with astyle
|
||||
|
||||
2017-08-18:
|
||||
- Add explicit casts to silence g++ warnings.
|
||||
86
targets/wasm-tacle/sequential/ammunition/README
Executable file
86
targets/wasm-tacle/sequential/ammunition/README
Executable file
@ -0,0 +1,86 @@
|
||||
This directory AMMUNITION contains reusable packages on C/C++:
|
||||
`allocate', `vlobject', `objstack', `hashtab', `commline', `ticker',
|
||||
`position', `errors', `bits', `arithm', `IEEE':
|
||||
o allocate
|
||||
Allocating and freeing memory with automatic fixing some
|
||||
allocation errors.
|
||||
o vlobject
|
||||
Work with variable length objects (VLO). Any number of bytes
|
||||
may be added to and removed from the end of VLO. If it is
|
||||
needed the memory allocated for storing variable length object
|
||||
may be expanded possibly with changing the object place. But
|
||||
between any additions of the bytes (or tailoring) the object
|
||||
place is not changed. To decrease number of changes of the
|
||||
object place the memory being allocated for the object is
|
||||
longer than the current object length.
|
||||
o objstack
|
||||
Work with stacks of objects (OS). Work with the object on the
|
||||
stack top is analogous to one with a variable length object.
|
||||
One motivation for the package is the problem of growing char
|
||||
strings in symbol tables. Memory for OS is allocated by
|
||||
segments. A segment may contain more one objects. The most
|
||||
recently allocated segment contains object on the top of OS.
|
||||
If there is not sufficient free memory for the top object than
|
||||
new segment is created and the top object is transferred into
|
||||
the new segment, i.e. there is not any memory reallocation.
|
||||
Therefore the top object may change its address. But other
|
||||
objects never change address.
|
||||
o hashtab
|
||||
Work with hash tables. The package permits to work
|
||||
simultaneously with several expandable hash tables. Besides
|
||||
insertion and search of elements the elements from the hash
|
||||
tables can be also removed. The table element can be only a
|
||||
pointer. The size of hash tables is not fixed. The hash
|
||||
table will be automatically expanded when its occupancy will
|
||||
became big.
|
||||
o position
|
||||
Work with source code positions. The package serves to
|
||||
support information about source positions of compiled files
|
||||
taking all included files into account.
|
||||
o errors
|
||||
Output of compiler messages. The package serves output
|
||||
one-pass or multi-pass compiler messages of various modes
|
||||
(errors, warnings, fatal, system errors and appended messages)
|
||||
in Unix style or for traditional listing. The package also
|
||||
permits adequate error reporting for included files.
|
||||
o commline
|
||||
Work with command line. The package implements features
|
||||
analogous to ones of public domain function `getopt'. The
|
||||
goal of the package creation is to use more readable language
|
||||
of command line description and to use command line
|
||||
description as help output of program.
|
||||
o ticker
|
||||
Simultaneous work with several tickers (timers).
|
||||
o bits
|
||||
Work with bit strings (copying, moving, setting, testing,
|
||||
comparison).
|
||||
o arithm
|
||||
Implementing host machine-independently arbitrary precision
|
||||
integer numbers arithmetic. The implementation of the package
|
||||
functions are not sufficiently efficient in order to use for
|
||||
run-time. The package functions are oriented to implement
|
||||
constant-folding in compilers, cross-compilers.
|
||||
o IEEE
|
||||
Implementing host machine-independently IEEE floating point
|
||||
arithmetic. The implementation of the package functions are
|
||||
not sufficiently efficient in order to use for run-time. The
|
||||
package functions are oriented to implement constant-folding
|
||||
in compilers, cross-compilers.
|
||||
|
||||
There are files with corresponding names and extensions `.h'
|
||||
(interface file for C/C++), `.c' (implementation file on C), and
|
||||
`.cpp' (implementation file on C++).
|
||||
|
||||
To install AMMUNITION see file INSTALL in the current directory.
|
||||
|
||||
There are also shell scripts for testing the package with
|
||||
corresponding names and extension `.tst'. Documentation of the
|
||||
reusable packages is in files `ammunition.txt', `ammunition.dvi',
|
||||
`ammunition.ps', `ammunition.info*', `ammunition*.html',
|
||||
`ammunition*.rtf' for C and `ammunition++.txt', `ammunition++.dvi',
|
||||
`ammunition++.ps', `ammunition++.info*', `ammunition++*.html',
|
||||
`ammunition++*.rtf'.
|
||||
|
||||
Please send bug reports and comments to vmakarov@fnmail.com
|
||||
|
||||
Vladimir Makarov
|
||||
1179
targets/wasm-tacle/sequential/ammunition/ammunition.c
Executable file
1179
targets/wasm-tacle/sequential/ammunition/ammunition.c
Executable file
File diff suppressed because it is too large
Load Diff
166
targets/wasm-tacle/sequential/ammunition/ammunition_libc.c
Executable file
166
targets/wasm-tacle/sequential/ammunition/ammunition_libc.c
Executable file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
Include section
|
||||
*/
|
||||
|
||||
#include "ammunition_string.h"
|
||||
#include "ammunition_stdio.h"
|
||||
#include "ammunition_stdlib.h"
|
||||
|
||||
|
||||
/*
|
||||
Standard library functions
|
||||
*/
|
||||
|
||||
char ammunition_isdigit( unsigned char c )
|
||||
{
|
||||
if ( ( c >= '0' ) & ( c <= '9' ) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ammunition_isspace( int c )
|
||||
{
|
||||
return ( c == ' ' ) | ( c == '\t' ) | ( c == '\n' ) | ( c == '\r' );
|
||||
}
|
||||
|
||||
void *ammunition_memcpy( void *dest, const void *src, size_t size )
|
||||
{
|
||||
size_t i;
|
||||
_Pragma( "loopbound min 2 max 6" )
|
||||
for ( i = 0; i < size; i++ )
|
||||
( ( unsigned char * )dest )[ i ] = ( ( unsigned char * )src )[ i ];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void *ammunition_memset( void *s, int c, size_t n )
|
||||
{
|
||||
size_t i;
|
||||
_Pragma( "loopbound min 0 max 4" )
|
||||
for ( i = 0; i < n; i++ )
|
||||
( ( unsigned char * )s )[ i ] = ( unsigned char )c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int ammunition_memcmp ( const void *mem1, const void *mem2, size_t size )
|
||||
{
|
||||
const unsigned char *p1 = ( const unsigned char * ) mem1,
|
||||
*p2 = ( const unsigned char * ) mem2;
|
||||
_Pragma( "loopbound min 0 max 4" )
|
||||
while ( size-- )
|
||||
if ( *p1 != *p2 )
|
||||
return ( *p1 - *p2 );
|
||||
else
|
||||
p1++, p2++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The following function is an analog of standard C function
|
||||
`memmove'. The function returns the first operand. */
|
||||
|
||||
void *ammunition_memmove ( void *s1, const void *s2, size_t n )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( ( ( char * ) s1 < ( char * ) s2 && ( char * ) s1 + n <= ( char * ) s2 )
|
||||
|| ( ( char * ) s2 < ( char * ) s1
|
||||
&& ( char * ) s2 + n <= ( char * ) s1 ) )
|
||||
return ( void * ) ammunition_memcpy ( s1, s2, n );
|
||||
if ( ( char * ) s1 < ( char * ) s2 && ( char * ) s1 + n > ( char * ) s2 ) {
|
||||
_Pragma( "loopbound min 0 max 4" )
|
||||
for ( i = 0; ( size_t ) i < n; i++ )
|
||||
( ( char * ) s1 ) [ i ] = ( ( char * ) s2 ) [ i ];
|
||||
} else {
|
||||
_Pragma( "loopbound min 0 max 4" )
|
||||
for ( i = n - 1; i >= 0; i-- )
|
||||
( ( char * ) s1 )[ i ] = ( ( char * ) s2 ) [ i ];
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
int ammunition_strcmp ( const char *str1, const char *str2 )
|
||||
{
|
||||
_Pragma( "loopbound min 1 max 11" )
|
||||
while ( *str1 && ( *str1 == *str2 ) )
|
||||
str1++, str2++;
|
||||
return *( const unsigned char * )str1 - *( const unsigned char * )str2;
|
||||
}
|
||||
|
||||
int ammunition_atoi ( const char *str )
|
||||
{
|
||||
int result = 0;
|
||||
int sign = ( str[ 0 ] == '-' ? -1 : 1 );
|
||||
|
||||
int readingPos = 0;
|
||||
if ( str[ 0 ] == '-' || str[ 0 ] == '+' )
|
||||
readingPos++;
|
||||
_Pragma( "loopbound min 1 max 7" )
|
||||
do {
|
||||
result *= 10;
|
||||
result += str[ readingPos++ ] - 48;
|
||||
} while ( str[ readingPos ] != 0 );
|
||||
|
||||
return sign * result;
|
||||
}
|
||||
|
||||
|
||||
int ammunition_sprintf_d( char *s, int number )
|
||||
{
|
||||
/* How many decimal digits do we need? */
|
||||
char digits = 0;
|
||||
unsigned char writePos = 0;
|
||||
long long copyOfNumber = number;
|
||||
_Pragma( "loopbound min 1 max 10" )
|
||||
do {
|
||||
digits++;
|
||||
copyOfNumber /= 10;
|
||||
} while ( copyOfNumber != 0 );
|
||||
|
||||
writePos = digits;
|
||||
if ( number < 0 ) {
|
||||
writePos++;
|
||||
s[ 0 ] = '-';
|
||||
}
|
||||
s[ writePos ] = 0;
|
||||
|
||||
copyOfNumber = number;
|
||||
_Pragma( "loopbound min 1 max 10" )
|
||||
do {
|
||||
s[ --writePos ] = 48 + ( ( copyOfNumber >= 0 ?
|
||||
copyOfNumber : -copyOfNumber ) % 10 );
|
||||
copyOfNumber /= 10;
|
||||
} while ( copyOfNumber != 0 );
|
||||
|
||||
return digits + ( number < 0 ? 1 : 0 );
|
||||
}
|
||||
|
||||
|
||||
int ammunition_sprintf_u( char *s, unsigned int number )
|
||||
{
|
||||
/* How many decimal digits do we need? */
|
||||
char digits = 0;
|
||||
unsigned char writePos = 0;
|
||||
unsigned long long copyOfNumber = number;
|
||||
_Pragma( "loopbound min 1 max 10" )
|
||||
do {
|
||||
digits++;
|
||||
copyOfNumber /= 10;
|
||||
} while ( copyOfNumber != 0 );
|
||||
|
||||
writePos = digits;
|
||||
s[ writePos ] = 0;
|
||||
|
||||
copyOfNumber = number;
|
||||
_Pragma( "loopbound min 1 max 10" )
|
||||
do {
|
||||
s[ --writePos ] = 48 + ( copyOfNumber % 10 );
|
||||
copyOfNumber /= 10;
|
||||
} while ( copyOfNumber != 0 );
|
||||
|
||||
return digits;
|
||||
}
|
||||
35
targets/wasm-tacle/sequential/ammunition/ammunition_limits.h
Executable file
35
targets/wasm-tacle/sequential/ammunition/ammunition_limits.h
Executable file
@ -0,0 +1,35 @@
|
||||
#ifndef AMMUNITION_LIMITS_H
|
||||
#define AMMUNITION_LIMITS_H
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
#ifndef SCHAR_MAX
|
||||
#define SCHAR_MAX 127
|
||||
#endif
|
||||
#ifndef SCHAR_MIN
|
||||
#define SCHAR_MIN (-128)
|
||||
#endif
|
||||
#ifndef USHRT_MAX
|
||||
#define USHRT_MAX 65535
|
||||
#endif
|
||||
#ifndef SHRT_MAX
|
||||
#define SHRT_MAX 32767
|
||||
#endif
|
||||
#ifndef SHRT_MIN
|
||||
#define SHRT_MIN (-32768)
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
#define UINT_MAX (INT_MAX * 2U + 1)
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 2147483647
|
||||
#endif
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (-INT_MAX-1)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef AMMUNITION_LIMITS_H */
|
||||
8
targets/wasm-tacle/sequential/ammunition/ammunition_stdio.h
Executable file
8
targets/wasm-tacle/sequential/ammunition/ammunition_stdio.h
Executable file
@ -0,0 +1,8 @@
|
||||
#ifndef AMMUNITION_STDIO_H
|
||||
#define AMMUNITION_STDIO_H
|
||||
|
||||
int ammunition_sprintf_d( char *s, int number );
|
||||
|
||||
int ammunition_sprintf_u( char *s, unsigned int number );
|
||||
|
||||
#endif
|
||||
6
targets/wasm-tacle/sequential/ammunition/ammunition_stdlib.h
Executable file
6
targets/wasm-tacle/sequential/ammunition/ammunition_stdlib.h
Executable file
@ -0,0 +1,6 @@
|
||||
#ifndef AMMUNITION_STDLIB_H
|
||||
#define AMMUNITION_STDLIB_H
|
||||
|
||||
int ammunition_atoi ( const char *str );
|
||||
|
||||
#endif
|
||||
18
targets/wasm-tacle/sequential/ammunition/ammunition_string.h
Executable file
18
targets/wasm-tacle/sequential/ammunition/ammunition_string.h
Executable file
@ -0,0 +1,18 @@
|
||||
#ifndef AMMUNITION_STRING_H
|
||||
#define AMMUNITION_STRING_H
|
||||
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/*
|
||||
Forward declaration of functions
|
||||
*/
|
||||
|
||||
void *ammunition_memcpy( void *, const void *, size_t );
|
||||
void *ammunition_memset( void *, int, size_t );
|
||||
int ammunition_memcmp ( const void *mem1, const void *mem2, size_t size );
|
||||
void *ammunition_memmove ( void *s1, const void *s2, size_t n );
|
||||
int ammunition_strcmp ( const char *str1, const char *str2 );
|
||||
|
||||
#endif /* AMMUNITION_STRING_H */
|
||||
|
||||
1383
targets/wasm-tacle/sequential/ammunition/arithm.c
Executable file
1383
targets/wasm-tacle/sequential/ammunition/arithm.c
Executable file
File diff suppressed because it is too large
Load Diff
123
targets/wasm-tacle/sequential/ammunition/arithm.h
Executable file
123
targets/wasm-tacle/sequential/ammunition/arithm.h
Executable file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
FILE NAME: arithm.h
|
||||
|
||||
TITLE: Include file of package for arbitrary precision integer
|
||||
arithmetic
|
||||
|
||||
DESCRIPTION: This header file contains ANSI C prototype definitions of
|
||||
the package functions and definitions of external
|
||||
variable of the package and C++ classes for arbitrary
|
||||
precision integer arithmetic.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __ARITHMETIC__
|
||||
#define __ARITHMETIC__
|
||||
|
||||
#include "ammunition_limits.h"
|
||||
|
||||
|
||||
/* This page contains definitions of variables and macros common for
|
||||
all package functions. */
|
||||
|
||||
/* The value of macro is suggested to be maximum length of integer operands
|
||||
The length of use integers should be not greater than this value. */
|
||||
|
||||
#define MAX_INTEGER_OPERAND_SIZE 128
|
||||
|
||||
/* The following macro value is sign of integer number (0 or 1) given
|
||||
as macro parameter. */
|
||||
|
||||
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
|
||||
|
||||
extern int ammunition_overflow_bit;
|
||||
|
||||
extern void ammunition_add_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2,
|
||||
void *result );
|
||||
extern void ammunition_add_integer ( int size, const void *op1, const void *op2,
|
||||
void *result );
|
||||
extern void ammunition_subtract_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_subtract_integer ( int size, const void *op1,
|
||||
const void *op2,
|
||||
void *result );
|
||||
extern void ammunition_multiply_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_multiply_integer ( int size, const void *op1,
|
||||
const void *op2,
|
||||
void *result );
|
||||
extern void ammunition_divide_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_divide_integer ( int size, const void *op1,
|
||||
const void *op2,
|
||||
void *result );
|
||||
extern void ammunition_unsigned_integer_remainder ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
|
||||
extern void ammunition_unsigned_integer_shift_right ( int size,
|
||||
const void *operand,
|
||||
int bits, void *result );
|
||||
extern void ammunition_integer_shift_right ( int size, const void *operand,
|
||||
int bits, void *result );
|
||||
extern void ammunition_integer_shift_left ( int size, const void *operand,
|
||||
int bits, void *result );
|
||||
extern void ammunition_unsigned_integer_shift_left ( int size,
|
||||
const void *operand,
|
||||
int bits, void *result );
|
||||
|
||||
extern void ammunition_integer_or ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_unsigned_integer_or ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_integer_and ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_unsigned_integer_and ( int size, const void *op1,
|
||||
const void *op2, void *result );
|
||||
extern void ammunition_integer_not ( int size, const void *operand,
|
||||
void *result );
|
||||
extern void ammunition_unsigned_integer_not ( int size, const void *operand,
|
||||
void *result );
|
||||
|
||||
extern int ammunition_eq_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2 );
|
||||
extern int ammunition_eq_integer ( int size, const void *op1, const void *op2 );
|
||||
extern int ammunition_ne_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2 );
|
||||
extern int ammunition_ne_integer ( int size, const void *op1, const void *op2 );
|
||||
extern int ammunition_gt_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2 );
|
||||
extern int ammunition_gt_integer ( int size, const void *op1, const void *op2 );
|
||||
extern int ammunition_lt_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2 );
|
||||
extern int ammunition_lt_integer ( int size, const void *op1, const void *op2 );
|
||||
extern int ammunition_ge_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2 );
|
||||
extern int ammunition_ge_integer ( int size, const void *op1, const void *op2 );
|
||||
extern int ammunition_le_unsigned_integer ( int size, const void *op1,
|
||||
const void *op2 );
|
||||
extern int ammunition_le_integer ( int size, const void *op1, const void *op2 );
|
||||
|
||||
extern void ammunition_change_unsigned_integer_size
|
||||
( int operand_size, const void *operand, int result_size, void *result );
|
||||
extern void ammunition_change_integer_size ( int operand_size,
|
||||
const void *operand,
|
||||
int result_size, void *result );
|
||||
|
||||
extern char *ammunition_unsigned_integer_to_string ( int size,
|
||||
const void *operand,
|
||||
char *result );
|
||||
extern char *ammunition_integer_to_string ( int size, const void *operand,
|
||||
char *result );
|
||||
|
||||
extern char *ammunition_unsigned_integer_from_string ( int size,
|
||||
const char *operand,
|
||||
void *result );
|
||||
extern char *ammunition_integer_from_string ( int size, const char *operand,
|
||||
void *result );
|
||||
|
||||
char ammunition_isdigit( unsigned char c );
|
||||
int ammunition_isspace( int c );
|
||||
|
||||
#endif /* #ifndef __ARITHMETIC__ */
|
||||
313
targets/wasm-tacle/sequential/ammunition/bits.c
Executable file
313
targets/wasm-tacle/sequential/ammunition/bits.c
Executable file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
|
||||
FILE NAME: bits.c
|
||||
|
||||
TITLE: Package for work with bits
|
||||
|
||||
DESCRIPTION: This file implements functions of the package for work
|
||||
with bit strings. A bit is given by address (start address) of
|
||||
byte from which counting bits starts and its displacement which
|
||||
is any non negative number of bit from the start address. The
|
||||
most significant bit of the start address byte has number 0.
|
||||
The bit string is given by its first bit and its length in
|
||||
bits.
|
||||
|
||||
*/
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
/* This function determines that given bit string contains only zero
|
||||
bits. The function retruns TRUE if all bits of given bit string
|
||||
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. */
|
||||
|
||||
int
|
||||
ammunition_is_zero_bit_string ( const void *start_byte, int bit_displacement,
|
||||
int bit_length )
|
||||
{
|
||||
const unsigned char *current_byte = ( unsigned const char * )start_byte;
|
||||
|
||||
if ( bit_length <= 0 )
|
||||
return 1 /* TRUE */;
|
||||
current_byte += bit_displacement / CHAR_BIT;
|
||||
bit_displacement %= CHAR_BIT;
|
||||
if ( bit_length < CHAR_BIT - bit_displacement )
|
||||
return ( ( ( *current_byte << bit_displacement )
|
||||
& ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) )
|
||||
& UCHAR_MAX ) == 0;
|
||||
else
|
||||
if ( bit_displacement != 0 ) {
|
||||
if ( ( ( *current_byte << bit_displacement ) & UCHAR_MAX ) != 0 )
|
||||
return 0 /* FALSE */;
|
||||
current_byte += 1;
|
||||
bit_length -= CHAR_BIT - bit_displacement;
|
||||
}
|
||||
_Pragma( "loopbound min 0 max 7" )
|
||||
while ( bit_length >= CHAR_BIT ) {
|
||||
if ( *current_byte != 0 )
|
||||
return 0 /* FALSE */;
|
||||
current_byte++;
|
||||
bit_length -= CHAR_BIT;
|
||||
}
|
||||
if ( bit_length > 0 && ( *current_byte >> ( CHAR_BIT - bit_length ) ) != 0 )
|
||||
return 0 /* FALSE */;
|
||||
return 1 /* TRUE */;
|
||||
}
|
||||
|
||||
/* This function sets up new value of all bits of given bit string.
|
||||
This function is analog of standard C function `memset'. Value of
|
||||
`bit_displacement' must be non-negative and can be greater than
|
||||
CHAR_BIT. */
|
||||
|
||||
void
|
||||
ammunition_bit_string_set ( void *start_byte, int bit_displacement, int bit,
|
||||
int bit_length )
|
||||
{
|
||||
unsigned char *current_byte = ( unsigned char * )start_byte;
|
||||
unsigned char filling_byte;
|
||||
int mask;
|
||||
|
||||
if ( bit_length <= 0 )
|
||||
return ;
|
||||
bit = bit != 0; /* 1 or 0 */
|
||||
filling_byte = ( bit ? UCHAR_MAX : 0 );
|
||||
current_byte += bit_displacement / CHAR_BIT;
|
||||
bit_displacement %= CHAR_BIT;
|
||||
if ( bit_displacement != 0 ) {
|
||||
mask = UCHAR_MAX << ( CHAR_BIT - bit_displacement );
|
||||
if ( bit_length < CHAR_BIT - bit_displacement )
|
||||
mask |= UCHAR_MAX >> ( bit_displacement + bit_length );
|
||||
*current_byte = ( *current_byte & mask ) | ( filling_byte & ~mask );
|
||||
current_byte += 1;
|
||||
bit_length -= CHAR_BIT - bit_displacement;
|
||||
}
|
||||
_Pragma( "loopbound min 0 max 8" )
|
||||
while ( bit_length >= CHAR_BIT ) {
|
||||
*current_byte = filling_byte;
|
||||
current_byte++;
|
||||
bit_length -= CHAR_BIT;
|
||||
}
|
||||
if ( bit_length > 0 )
|
||||
*current_byte
|
||||
= ( *current_byte & ~( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) )
|
||||
| ( filling_byte & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) );
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string. This
|
||||
function is analog of standard C function `memcpy'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string must
|
||||
be non-overlapped. */
|
||||
|
||||
void
|
||||
ammunition_bit_string_copy ( void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length )
|
||||
{
|
||||
unsigned char *current_to_byte = ( unsigned char * )to;
|
||||
const unsigned char *current_from_byte = ( unsigned const char * )from;
|
||||
int byte;
|
||||
int mask;
|
||||
|
||||
if ( bit_length <= 0 )
|
||||
return ;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT;
|
||||
to_bit_displacement %= CHAR_BIT;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT;
|
||||
from_bit_displacement %= CHAR_BIT;
|
||||
_Pragma( "loopbound min 0 max 7" )
|
||||
while ( 1 ) {
|
||||
byte = ( ( ( *current_from_byte << from_bit_displacement ) & UCHAR_MAX )
|
||||
| ( from_bit_displacement != 0
|
||||
&& bit_length > ( CHAR_BIT - from_bit_displacement )
|
||||
? current_from_byte [ 1 ] >> ( CHAR_BIT - from_bit_displacement )
|
||||
: 0 ) );
|
||||
if ( bit_length <= CHAR_BIT )
|
||||
break;
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
*current_to_byte
|
||||
= ( *current_to_byte
|
||||
& ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) ) )
|
||||
| ( byte >> to_bit_displacement );
|
||||
if ( to_bit_displacement != 0 )
|
||||
current_to_byte [ 1 ]
|
||||
= ( current_to_byte [ 1 ] & ( UCHAR_MAX >> to_bit_displacement ) )
|
||||
| ( byte << ( CHAR_BIT - to_bit_displacement ) );
|
||||
bit_length -= CHAR_BIT;
|
||||
current_from_byte++;
|
||||
current_to_byte++;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
mask = ( ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) )
|
||||
| ( UCHAR_MAX >> ( to_bit_displacement + bit_length ) ) );
|
||||
*current_to_byte
|
||||
= ( *current_to_byte & mask ) | ( ( byte >> to_bit_displacement ) & ~mask );
|
||||
bit_length -= CHAR_BIT - to_bit_displacement;
|
||||
if ( bit_length > 0 )
|
||||
current_to_byte [ 1 ]
|
||||
= ( current_to_byte [ 1 ] & ( UCHAR_MAX >> bit_length ) )
|
||||
| ( ( byte << ( CHAR_BIT - to_bit_displacement ) )
|
||||
& ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) );
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string. Copying
|
||||
starts with the last bits of the bit strings. This function is
|
||||
used by function `bit_string_move'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string must
|
||||
be non-overlapped. */
|
||||
|
||||
void ammunition_reverse_bit_string_copy ( void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length )
|
||||
{
|
||||
unsigned char *current_to_byte = ( unsigned char * )to;
|
||||
const unsigned char *current_from_byte = ( unsigned const char * )from;
|
||||
int byte;
|
||||
int mask;
|
||||
|
||||
if ( bit_length <= 0 )
|
||||
return ;
|
||||
to_bit_displacement += bit_length - 1;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
|
||||
to_bit_displacement %= CHAR_BIT; /* last bit */
|
||||
from_bit_displacement += bit_length - 1;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
|
||||
from_bit_displacement %= CHAR_BIT; /* last bit */
|
||||
_Pragma( "loopbound min 0 max 7" )
|
||||
while ( 1 ) {
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
byte = ( ( *current_from_byte >> ( CHAR_BIT - 1 - from_bit_displacement ) )
|
||||
| ( ( from_bit_displacement != CHAR_BIT - 1
|
||||
&& bit_length > from_bit_displacement + 1
|
||||
? current_from_byte [ -1 ] << ( from_bit_displacement + 1 )
|
||||
: 0 )
|
||||
& UCHAR_MAX ) );
|
||||
if ( bit_length <= CHAR_BIT )
|
||||
break;
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
*current_to_byte
|
||||
= ( *current_to_byte & ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) )
|
||||
| ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) );
|
||||
if ( to_bit_displacement != CHAR_BIT - 1 )
|
||||
current_to_byte [ -1 ]
|
||||
= ( current_to_byte [ -1 ]
|
||||
& ( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement ) ) )
|
||||
| ( byte >> ( to_bit_displacement + 1 ) );
|
||||
bit_length -= CHAR_BIT;
|
||||
current_from_byte--;
|
||||
current_to_byte--;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
mask = ( ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) |
|
||||
( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement
|
||||
+ bit_length ) ) );
|
||||
*current_to_byte
|
||||
= ( *current_to_byte & mask )
|
||||
| ( ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) ) & ~mask );
|
||||
bit_length -= to_bit_displacement + 1;
|
||||
if ( bit_length > 0 )
|
||||
current_to_byte [ -1 ]
|
||||
= ( current_to_byte [ -1 ] & ( UCHAR_MAX << bit_length ) )
|
||||
| ( byte >> ( to_bit_displacement + 1 )
|
||||
& ( UCHAR_MAX >> ( CHAR_BIT - bit_length ) ) );
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string with the aid
|
||||
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
|
||||
function is analog of standard C function `memmove'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string can
|
||||
be overlapped. */
|
||||
|
||||
void
|
||||
ammunition_bit_string_move ( void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length )
|
||||
{
|
||||
unsigned char *current_to_byte = ( unsigned char * )to;
|
||||
const unsigned char *current_from_byte = ( unsigned const char * )from;
|
||||
|
||||
if ( bit_length <= 0 )
|
||||
return ;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT;
|
||||
to_bit_displacement %= CHAR_BIT;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT;
|
||||
from_bit_displacement %= CHAR_BIT;
|
||||
if ( current_from_byte > current_to_byte
|
||||
|| ( current_from_byte == current_to_byte
|
||||
&& from_bit_displacement > to_bit_displacement ) )
|
||||
ammunition_bit_string_copy ( current_to_byte, to_bit_displacement,
|
||||
current_from_byte, from_bit_displacement,
|
||||
bit_length );
|
||||
else
|
||||
ammunition_reverse_bit_string_copy ( current_to_byte, to_bit_displacement,
|
||||
current_from_byte,
|
||||
from_bit_displacement, bit_length );
|
||||
}
|
||||
|
||||
/* This function compares bit strings. This function is analog of
|
||||
standard C function `memcmp'. The function returns 0 if the bit
|
||||
strings are equal, 1 if the first bit string is greater than the
|
||||
second, -1 if the first bit string is less than the first. Values
|
||||
of `bit_displacement1' and `bit_displacement2' must be non-negative
|
||||
and can be greater than CHAR_BIT. */
|
||||
|
||||
int
|
||||
ammunition_bit_string_comparison ( const void *str1, int bit_displacement1,
|
||||
const void *str2, int bit_displacement2,
|
||||
int bit_length )
|
||||
{
|
||||
const unsigned char *current_byte1 = ( unsigned const char * )str1;
|
||||
const unsigned char *current_byte2 = ( unsigned const char * )str2;
|
||||
int byte1;
|
||||
int byte2;
|
||||
int mask;
|
||||
|
||||
if ( bit_length <= 0 )
|
||||
return 0;
|
||||
current_byte1 += bit_displacement1 / CHAR_BIT;
|
||||
bit_displacement1 %= CHAR_BIT;
|
||||
current_byte2 += bit_displacement2 / CHAR_BIT;
|
||||
bit_displacement2 %= CHAR_BIT;
|
||||
_Pragma( "loopbound min 0 max 7" )
|
||||
while ( 1 ) {
|
||||
byte1 = ( ( ( *current_byte1 << bit_displacement1 ) & UCHAR_MAX )
|
||||
| ( bit_displacement1 != 0
|
||||
/* Shift is correct when to_bit_displacement == 0
|
||||
because its value is less than word bit size. */
|
||||
&& bit_length > CHAR_BIT - bit_displacement1
|
||||
? current_byte1 [ 1 ] >> ( CHAR_BIT - bit_displacement1 )
|
||||
: 0 ) );
|
||||
byte2 = ( ( ( *current_byte2 << bit_displacement2 ) & UCHAR_MAX )
|
||||
| ( bit_displacement2 != 0
|
||||
&& bit_length > CHAR_BIT - bit_displacement2
|
||||
? current_byte2 [ 1 ] >> ( CHAR_BIT - bit_displacement2 )
|
||||
: 0 ) );
|
||||
if ( bit_length <= CHAR_BIT )
|
||||
break;
|
||||
if ( byte1 > byte2 )
|
||||
return 1;
|
||||
else
|
||||
if ( byte1 < byte2 )
|
||||
return -1;
|
||||
bit_length -= CHAR_BIT;
|
||||
current_byte2++;
|
||||
current_byte1++;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its value
|
||||
is less than word bit size. */
|
||||
mask = UCHAR_MAX << ( CHAR_BIT - bit_length );
|
||||
if ( ( byte1 & mask ) > ( byte2 & mask ) )
|
||||
return 1;
|
||||
else
|
||||
if ( ( byte1 & mask ) < ( byte2 & mask ) )
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
60
targets/wasm-tacle/sequential/ammunition/bits.h
Executable file
60
targets/wasm-tacle/sequential/ammunition/bits.h
Executable file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
FILE NAME: bits.h
|
||||
|
||||
TITLE: Include file of package for work with bits
|
||||
|
||||
DESCRIPTION:
|
||||
This is header file contains macros and the ANSI C prototype
|
||||
definitions for the package for work with bits and bit strings
|
||||
and C++ class for work with bits and bit strings. A bit is
|
||||
given by address (start address) of byte from which counting
|
||||
bits starts and its displacement which is any non negative
|
||||
number of bit from the start address. The most significant bit
|
||||
of the start address byte has number 0. The bit string is
|
||||
given by its first bit and its length in bits.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __BITS__
|
||||
#define __BITS__
|
||||
|
||||
#include "ammunition_limits.h"
|
||||
|
||||
/* This macro value returns bit vlaue (0 or 1) with given bit
|
||||
displacement (0, 1, ...). The macro has side effects! Value of
|
||||
`bit_displacement' must be nonegative and can be greater than
|
||||
CHAR_BIT. */
|
||||
|
||||
#define BIT(start_byte, bit_displacement)\
|
||||
((((const char *) (start_byte)) [(bit_displacement) / CHAR_BIT]\
|
||||
>> (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & 1)
|
||||
|
||||
|
||||
/* This macro value sets up new value (must be `0' or `1') of a given
|
||||
bit (bit displacement starts with 0). The macro has side effects!
|
||||
Value of `bit_displacement' must be nonegative and can be greater
|
||||
than CHAR_BIT. */
|
||||
|
||||
#define SET_BIT(start_byte, bit_displacement, bit)\
|
||||
(((char *) (start_byte)) [(bit_displacement) / CHAR_BIT]\
|
||||
= (((char *) (start_byte)) [(bit_displacement) / CHAR_BIT]\
|
||||
& ~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))\
|
||||
| ((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
|
||||
|
||||
int ammunition_is_zero_bit_string ( const void *start_byte,
|
||||
int bit_displacement,
|
||||
int bit_length );
|
||||
void ammunition_bit_string_set ( void *start_byte, int bit_displacement,
|
||||
int bit,
|
||||
int bit_length );
|
||||
void ammunition_bit_string_copy ( void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length );
|
||||
void ammunition_bit_string_move ( void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length );
|
||||
int ammunition_bit_string_comparison ( const void *str1, int bit_displacement1,
|
||||
const void *str2, int bit_displacement2,
|
||||
int bit_length );
|
||||
|
||||
#endif /* #ifndef __BITS__ */
|
||||
BIN
targets/wasm-tacle/sequential/ammunition/generated/default/ammunition.wasm
Executable file
BIN
targets/wasm-tacle/sequential/ammunition/generated/default/ammunition.wasm
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Include section
|
||||
*/
|
||||
|
||||
#include "ammunition_stdio.h"
|
||||
#include "ammunition_stdlib.h"
|
||||
#include "ammunition_string.h"
|
||||
|
||||
/*
|
||||
Standard library functions
|
||||
*/
|
||||
|
||||
// Wasm loop bounds
|
||||
|
||||
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
|
||||
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
|
||||
|
||||
char
|
||||
ammunition_isdigit(unsigned char c) {
|
||||
if ((c >= '0') & (c <= '9'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ammunition_isspace(int c) {
|
||||
return (c == ' ') | (c == '\t') | (c == '\n') | (c == '\r');
|
||||
}
|
||||
|
||||
void *
|
||||
ammunition_memcpy(void *dest, const void *src, size_t size) {
|
||||
size_t i;
|
||||
__pragma_loopbound(2, 6);
|
||||
for (i = 0; i < size; i++)
|
||||
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *
|
||||
ammunition_memset(void *s, int c, size_t n) {
|
||||
size_t i;
|
||||
__pragma_loopbound(0, 4);
|
||||
for (i = 0; i < n; i++)
|
||||
((unsigned char *) s)[i] = (unsigned char) c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
ammunition_memcmp(const void *mem1, const void *mem2, size_t size) {
|
||||
const unsigned char *p1 = (const unsigned char *) mem1,
|
||||
*p2 = (const unsigned char *) mem2;
|
||||
__pragma_loopbound(0, 4);
|
||||
while (size--)
|
||||
if (*p1 != *p2)
|
||||
return (*p1 - *p2);
|
||||
else
|
||||
p1++, p2++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The following function is an analog of standard C function
|
||||
`memmove'. The function returns the first operand. */
|
||||
|
||||
void *
|
||||
ammunition_memmove(void *s1, const void *s2, size_t n) {
|
||||
int i;
|
||||
|
||||
if (((char *) s1 < (char *) s2 && (char *) s1 + n <= (char *) s2) ||
|
||||
((char *) s2 < (char *) s1 && (char *) s2 + n <= (char *) s1))
|
||||
return (void *) ammunition_memcpy(s1, s2, n);
|
||||
if ((char *) s1 < (char *) s2 && (char *) s1 + n > (char *) s2) {
|
||||
__pragma_loopbound(0, 4);
|
||||
for (i = 0; (size_t) i < n; i++)
|
||||
((char *) s1)[i] = ((char *) s2)[i];
|
||||
} else {
|
||||
__pragma_loopbound(0, 4);
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
((char *) s1)[i] = ((char *) s2)[i];
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
int
|
||||
ammunition_strcmp(const char *str1, const char *str2) {
|
||||
__pragma_loopbound(1, 11);
|
||||
while (*str1 && (*str1 == *str2))
|
||||
str1++, str2++;
|
||||
return *(const unsigned char *) str1 - *(const unsigned char *) str2;
|
||||
}
|
||||
|
||||
int
|
||||
ammunition_atoi(const char *str) {
|
||||
int result = 0;
|
||||
int sign = (str[0] == '-' ? -1 : 1);
|
||||
|
||||
int readingPos = 0;
|
||||
if (str[0] == '-' || str[0] == '+')
|
||||
readingPos++;
|
||||
__pragma_loopbound(1, 7);
|
||||
do {
|
||||
result *= 10;
|
||||
result += str[readingPos++] - 48;
|
||||
} while (str[readingPos] != 0);
|
||||
|
||||
return sign * result;
|
||||
}
|
||||
|
||||
int
|
||||
ammunition_sprintf_d(char *s, int number) {
|
||||
/* How many decimal digits do we need? */
|
||||
char digits = 0;
|
||||
unsigned char writePos = 0;
|
||||
long long copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
digits++;
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
writePos = digits;
|
||||
if (number < 0) {
|
||||
writePos++;
|
||||
s[0] = '-';
|
||||
}
|
||||
s[writePos] = 0;
|
||||
|
||||
copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
s[--writePos] =
|
||||
48 + ((copyOfNumber >= 0 ? copyOfNumber : -copyOfNumber) % 10);
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
return digits + (number < 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
int
|
||||
ammunition_sprintf_u(char *s, unsigned int number) {
|
||||
/* How many decimal digits do we need? */
|
||||
char digits = 0;
|
||||
unsigned char writePos = 0;
|
||||
unsigned long long copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
digits++;
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
writePos = digits;
|
||||
s[writePos] = 0;
|
||||
|
||||
copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
s[--writePos] = 48 + (copyOfNumber % 10);
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
return digits;
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
|
||||
#ifndef AMMUNITION_LIMITS_H
|
||||
#define AMMUNITION_LIMITS_H
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
#ifndef SCHAR_MAX
|
||||
#define SCHAR_MAX 127
|
||||
#endif
|
||||
#ifndef SCHAR_MIN
|
||||
#define SCHAR_MIN (-128)
|
||||
#endif
|
||||
#ifndef USHRT_MAX
|
||||
#define USHRT_MAX 65535
|
||||
#endif
|
||||
#ifndef SHRT_MAX
|
||||
#define SHRT_MAX 32767
|
||||
#endif
|
||||
#ifndef SHRT_MIN
|
||||
#define SHRT_MIN (-32768)
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
#define UINT_MAX (INT_MAX * 2U + 1)
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 2147483647
|
||||
#endif
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef AMMUNITION_LIMITS_H */
|
||||
@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef AMMUNITION_STDIO_H
|
||||
#define AMMUNITION_STDIO_H
|
||||
|
||||
int ammunition_sprintf_d(char *s, int number);
|
||||
|
||||
int ammunition_sprintf_u(char *s, unsigned int number);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef AMMUNITION_STDLIB_H
|
||||
#define AMMUNITION_STDLIB_H
|
||||
|
||||
int ammunition_atoi(const char *str);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,17 @@
|
||||
|
||||
#ifndef AMMUNITION_STRING_H
|
||||
#define AMMUNITION_STRING_H
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/*
|
||||
Forward declaration of functions
|
||||
*/
|
||||
|
||||
void *ammunition_memcpy(void *, const void *, size_t);
|
||||
void *ammunition_memset(void *, int, size_t);
|
||||
int ammunition_memcmp(const void *mem1, const void *mem2, size_t size);
|
||||
void *ammunition_memmove(void *s1, const void *s2, size_t n);
|
||||
int ammunition_strcmp(const char *str1, const char *str2);
|
||||
|
||||
#endif /* AMMUNITION_STRING_H */
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,105 @@
|
||||
/*
|
||||
FILE NAME: arithm.h
|
||||
|
||||
TITLE: Include file of package for arbitrary precision integer
|
||||
arithmetic
|
||||
|
||||
DESCRIPTION: This header file contains ANSI C prototype definitions of
|
||||
the package functions and definitions of external
|
||||
variable of the package and C++ classes for arbitrary
|
||||
precision integer arithmetic.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ARITHMETIC__
|
||||
#define __ARITHMETIC__
|
||||
|
||||
#include "ammunition_limits.h"
|
||||
|
||||
/* This page contains definitions of variables and macros common for
|
||||
all package functions. */
|
||||
|
||||
/* The value of macro is suggested to be maximum length of integer operands
|
||||
The length of use integers should be not greater than this value. */
|
||||
|
||||
#define MAX_INTEGER_OPERAND_SIZE 128
|
||||
|
||||
/* The following macro value is sign of integer number (0 or 1) given
|
||||
as macro parameter. */
|
||||
|
||||
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
|
||||
|
||||
extern int ammunition_overflow_bit;
|
||||
|
||||
void ammunition_add_unsigned_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_add_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_subtract_unsigned_integer(int size, const void *op1,
|
||||
const void *op2, void *result);
|
||||
void ammunition_subtract_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_multiply_unsigned_integer(int size, const void *op1,
|
||||
const void *op2, void *result);
|
||||
void ammunition_multiply_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_divide_unsigned_integer(int size, const void *op1,
|
||||
const void *op2, void *result);
|
||||
void ammunition_divide_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_unsigned_integer_remainder(int size, const void *op1,
|
||||
const void *op2, void *result);
|
||||
|
||||
void ammunition_unsigned_integer_shift_right(int size, const void *operand,
|
||||
int bits, void *result);
|
||||
void ammunition_integer_shift_right(int size, const void *operand, int bits,
|
||||
void *result);
|
||||
void ammunition_integer_shift_left(int size, const void *operand, int bits,
|
||||
void *result);
|
||||
void ammunition_unsigned_integer_shift_left(int size, const void *operand,
|
||||
int bits, void *result);
|
||||
|
||||
void ammunition_integer_or(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_unsigned_integer_or(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_integer_and(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_unsigned_integer_and(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
void ammunition_integer_not(int size, const void *operand, void *result);
|
||||
void ammunition_unsigned_integer_not(int size, const void *operand,
|
||||
void *result);
|
||||
|
||||
int ammunition_eq_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_eq_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_ne_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_ne_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_gt_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_gt_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_lt_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_lt_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_ge_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_ge_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_le_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
int ammunition_le_integer(int size, const void *op1, const void *op2);
|
||||
|
||||
void ammunition_change_unsigned_integer_size(int operand_size,
|
||||
const void *operand,
|
||||
int result_size, void *result);
|
||||
void ammunition_change_integer_size(int operand_size, const void *operand,
|
||||
int result_size, void *result);
|
||||
|
||||
char *ammunition_unsigned_integer_to_string(int size, const void *operand,
|
||||
char *result);
|
||||
char *ammunition_integer_to_string(int size, const void *operand, char *result);
|
||||
|
||||
char *ammunition_unsigned_integer_from_string(int size, const char *operand,
|
||||
void *result);
|
||||
char *ammunition_integer_from_string(int size, const char *operand,
|
||||
void *result);
|
||||
|
||||
char ammunition_isdigit(unsigned char c);
|
||||
int ammunition_isspace(int c);
|
||||
|
||||
#endif /* #ifndef __ARITHMETIC__ */
|
||||
@ -0,0 +1,305 @@
|
||||
/*
|
||||
|
||||
FILE NAME: bits.c
|
||||
|
||||
TITLE: Package for work with bits
|
||||
|
||||
DESCRIPTION: This file implements functions of the package for work
|
||||
with bit strings. A bit is given by address (start address) of
|
||||
byte from which counting bits starts and its displacement which
|
||||
is any non negative number of bit from the start address. The
|
||||
most significant bit of the start address byte has number 0.
|
||||
The bit string is given by its first bit and its length in
|
||||
bits.
|
||||
|
||||
*/
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
/* This function determines that given bit string contains only zero
|
||||
bits. The function retruns TRUE if all bits of given bit string
|
||||
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. */
|
||||
|
||||
// Wasm loop bounds
|
||||
|
||||
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
|
||||
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
|
||||
|
||||
int
|
||||
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
|
||||
int bit_length) {
|
||||
const unsigned char *current_byte = (unsigned const char *) start_byte;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return 1 /* TRUE */;
|
||||
current_byte += bit_displacement / CHAR_BIT;
|
||||
bit_displacement %= CHAR_BIT;
|
||||
if (bit_length < CHAR_BIT - bit_displacement)
|
||||
return (((*current_byte << bit_displacement) &
|
||||
(UCHAR_MAX << (CHAR_BIT - bit_length))) &
|
||||
UCHAR_MAX) == 0;
|
||||
else if (bit_displacement != 0) {
|
||||
if (((*current_byte << bit_displacement) & UCHAR_MAX) != 0)
|
||||
return 0 /* FALSE */;
|
||||
current_byte += 1;
|
||||
bit_length -= CHAR_BIT - bit_displacement;
|
||||
}
|
||||
__pragma_loopbound(0, 7);
|
||||
while (bit_length >= CHAR_BIT) {
|
||||
if (*current_byte != 0)
|
||||
return 0 /* FALSE */;
|
||||
current_byte++;
|
||||
bit_length -= CHAR_BIT;
|
||||
}
|
||||
if (bit_length > 0 && (*current_byte >> (CHAR_BIT - bit_length)) != 0)
|
||||
return 0 /* FALSE */;
|
||||
return 1 /* TRUE */;
|
||||
}
|
||||
|
||||
/* This function sets up new value of all bits of given bit string.
|
||||
This function is analog of standard C function `memset'. Value of
|
||||
`bit_displacement' must be non-negative and can be greater than
|
||||
CHAR_BIT. */
|
||||
|
||||
void
|
||||
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
|
||||
int bit_length) {
|
||||
unsigned char *current_byte = (unsigned char *) start_byte;
|
||||
unsigned char filling_byte;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
bit = bit != 0; /* 1 or 0 */
|
||||
filling_byte = (bit ? UCHAR_MAX : 0);
|
||||
current_byte += bit_displacement / CHAR_BIT;
|
||||
bit_displacement %= CHAR_BIT;
|
||||
if (bit_displacement != 0) {
|
||||
mask = UCHAR_MAX << (CHAR_BIT - bit_displacement);
|
||||
if (bit_length < CHAR_BIT - bit_displacement)
|
||||
mask |= UCHAR_MAX >> (bit_displacement + bit_length);
|
||||
*current_byte = (*current_byte & mask) | (filling_byte & ~mask);
|
||||
current_byte += 1;
|
||||
bit_length -= CHAR_BIT - bit_displacement;
|
||||
}
|
||||
__pragma_loopbound(0, 8);
|
||||
while (bit_length >= CHAR_BIT) {
|
||||
*current_byte = filling_byte;
|
||||
current_byte++;
|
||||
bit_length -= CHAR_BIT;
|
||||
}
|
||||
if (bit_length > 0)
|
||||
*current_byte =
|
||||
(*current_byte & ~(UCHAR_MAX << (CHAR_BIT - bit_length))) |
|
||||
(filling_byte & (UCHAR_MAX << (CHAR_BIT - bit_length)));
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string. This
|
||||
function is analog of standard C function `memcpy'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string must
|
||||
be non-overlapped. */
|
||||
|
||||
void
|
||||
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
|
||||
int from_bit_displacement, int bit_length) {
|
||||
unsigned char *current_to_byte = (unsigned char *) to;
|
||||
const unsigned char *current_from_byte = (unsigned const char *) from;
|
||||
int byte;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT;
|
||||
to_bit_displacement %= CHAR_BIT;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT;
|
||||
from_bit_displacement %= CHAR_BIT;
|
||||
__pragma_loopbound(0, 7);
|
||||
while (1) {
|
||||
byte =
|
||||
(((*current_from_byte << from_bit_displacement) & UCHAR_MAX) |
|
||||
(from_bit_displacement != 0 &&
|
||||
bit_length > (CHAR_BIT - from_bit_displacement)
|
||||
? current_from_byte[1] >> (CHAR_BIT - from_bit_displacement)
|
||||
: 0));
|
||||
if (bit_length <= CHAR_BIT)
|
||||
break;
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
*current_to_byte = (*current_to_byte &
|
||||
(UCHAR_MAX << (CHAR_BIT - to_bit_displacement))) |
|
||||
(byte >> to_bit_displacement);
|
||||
if (to_bit_displacement != 0)
|
||||
current_to_byte[1] =
|
||||
(current_to_byte[1] & (UCHAR_MAX >> to_bit_displacement)) |
|
||||
(byte << (CHAR_BIT - to_bit_displacement));
|
||||
bit_length -= CHAR_BIT;
|
||||
current_from_byte++;
|
||||
current_to_byte++;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
mask = ((UCHAR_MAX << (CHAR_BIT - to_bit_displacement)) |
|
||||
(UCHAR_MAX >> (to_bit_displacement + bit_length)));
|
||||
*current_to_byte =
|
||||
(*current_to_byte & mask) | ((byte >> to_bit_displacement) & ~mask);
|
||||
bit_length -= CHAR_BIT - to_bit_displacement;
|
||||
if (bit_length > 0)
|
||||
current_to_byte[1] = (current_to_byte[1] & (UCHAR_MAX >> bit_length)) |
|
||||
((byte << (CHAR_BIT - to_bit_displacement)) &
|
||||
(UCHAR_MAX << (CHAR_BIT - bit_length)));
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string. Copying
|
||||
starts with the last bits of the bit strings. This function is
|
||||
used by function `bit_string_move'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string must
|
||||
be non-overlapped. */
|
||||
|
||||
void
|
||||
ammunition_reverse_bit_string_copy(void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length) {
|
||||
unsigned char *current_to_byte = (unsigned char *) to;
|
||||
const unsigned char *current_from_byte = (unsigned const char *) from;
|
||||
int byte;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
to_bit_displacement += bit_length - 1;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
|
||||
to_bit_displacement %= CHAR_BIT; /* last bit */
|
||||
from_bit_displacement += bit_length - 1;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
|
||||
from_bit_displacement %= CHAR_BIT; /* last bit */
|
||||
__pragma_loopbound(0, 7);
|
||||
while (1) {
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
byte = ((*current_from_byte >> (CHAR_BIT - 1 - from_bit_displacement)) |
|
||||
((from_bit_displacement != CHAR_BIT - 1 &&
|
||||
bit_length > from_bit_displacement + 1
|
||||
? current_from_byte[-1] << (from_bit_displacement + 1)
|
||||
: 0) &
|
||||
UCHAR_MAX));
|
||||
if (bit_length <= CHAR_BIT)
|
||||
break;
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
*current_to_byte =
|
||||
(*current_to_byte & (UCHAR_MAX >> (to_bit_displacement + 1))) |
|
||||
(byte << (CHAR_BIT - 1 - to_bit_displacement));
|
||||
if (to_bit_displacement != CHAR_BIT - 1)
|
||||
current_to_byte[-1] =
|
||||
(current_to_byte[-1] &
|
||||
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement))) |
|
||||
(byte >> (to_bit_displacement + 1));
|
||||
bit_length -= CHAR_BIT;
|
||||
current_from_byte--;
|
||||
current_to_byte--;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
mask = ((UCHAR_MAX >> (to_bit_displacement + 1)) |
|
||||
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement + bit_length)));
|
||||
*current_to_byte = (*current_to_byte & mask) |
|
||||
((byte << (CHAR_BIT - 1 - to_bit_displacement)) & ~mask);
|
||||
bit_length -= to_bit_displacement + 1;
|
||||
if (bit_length > 0)
|
||||
current_to_byte[-1] =
|
||||
(current_to_byte[-1] & (UCHAR_MAX << bit_length)) |
|
||||
(byte >> (to_bit_displacement + 1) &
|
||||
(UCHAR_MAX >> (CHAR_BIT - bit_length)));
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string with the aid
|
||||
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
|
||||
function is analog of standard C function `memmove'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string can
|
||||
be overlapped. */
|
||||
|
||||
void
|
||||
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
|
||||
int from_bit_displacement, int bit_length) {
|
||||
unsigned char *current_to_byte = (unsigned char *) to;
|
||||
const unsigned char *current_from_byte = (unsigned const char *) from;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT;
|
||||
to_bit_displacement %= CHAR_BIT;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT;
|
||||
from_bit_displacement %= CHAR_BIT;
|
||||
if (current_from_byte > current_to_byte ||
|
||||
(current_from_byte == current_to_byte &&
|
||||
from_bit_displacement > to_bit_displacement))
|
||||
ammunition_bit_string_copy(current_to_byte, to_bit_displacement,
|
||||
current_from_byte, from_bit_displacement,
|
||||
bit_length);
|
||||
else
|
||||
ammunition_reverse_bit_string_copy(current_to_byte, to_bit_displacement,
|
||||
current_from_byte,
|
||||
from_bit_displacement, bit_length);
|
||||
}
|
||||
|
||||
/* This function compares bit strings. This function is analog of
|
||||
standard C function `memcmp'. The function returns 0 if the bit
|
||||
strings are equal, 1 if the first bit string is greater than the
|
||||
second, -1 if the first bit string is less than the first. Values
|
||||
of `bit_displacement1' and `bit_displacement2' must be non-negative
|
||||
and can be greater than CHAR_BIT. */
|
||||
|
||||
int
|
||||
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
|
||||
const void *str2, int bit_displacement2,
|
||||
int bit_length) {
|
||||
const unsigned char *current_byte1 = (unsigned const char *) str1;
|
||||
const unsigned char *current_byte2 = (unsigned const char *) str2;
|
||||
int byte1;
|
||||
int byte2;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return 0;
|
||||
current_byte1 += bit_displacement1 / CHAR_BIT;
|
||||
bit_displacement1 %= CHAR_BIT;
|
||||
current_byte2 += bit_displacement2 / CHAR_BIT;
|
||||
bit_displacement2 %= CHAR_BIT;
|
||||
__pragma_loopbound(0, 7);
|
||||
while (1) {
|
||||
byte1 = (((*current_byte1 << bit_displacement1) & UCHAR_MAX) |
|
||||
(bit_displacement1 != 0
|
||||
/* Shift is correct when to_bit_displacement == 0
|
||||
because its value is less than word bit size. */
|
||||
&& bit_length > CHAR_BIT - bit_displacement1
|
||||
? current_byte1[1] >> (CHAR_BIT - bit_displacement1)
|
||||
: 0));
|
||||
byte2 = (((*current_byte2 << bit_displacement2) & UCHAR_MAX) |
|
||||
(bit_displacement2 != 0 &&
|
||||
bit_length > CHAR_BIT - bit_displacement2
|
||||
? current_byte2[1] >> (CHAR_BIT - bit_displacement2)
|
||||
: 0));
|
||||
if (bit_length <= CHAR_BIT)
|
||||
break;
|
||||
if (byte1 > byte2)
|
||||
return 1;
|
||||
else if (byte1 < byte2)
|
||||
return -1;
|
||||
bit_length -= CHAR_BIT;
|
||||
current_byte2++;
|
||||
current_byte1++;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its value
|
||||
is less than word bit size. */
|
||||
mask = UCHAR_MAX << (CHAR_BIT - bit_length);
|
||||
if ((byte1 & mask) > (byte2 & mask))
|
||||
return 1;
|
||||
else if ((byte1 & mask) < (byte2 & mask))
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
FILE NAME: bits.h
|
||||
|
||||
TITLE: Include file of package for work with bits
|
||||
|
||||
DESCRIPTION:
|
||||
This is header file contains macros and the ANSI C prototype
|
||||
definitions for the package for work with bits and bit strings
|
||||
and C++ class for work with bits and bit strings. A bit is
|
||||
given by address (start address) of byte from which counting
|
||||
bits starts and its displacement which is any non negative
|
||||
number of bit from the start address. The most significant bit
|
||||
of the start address byte has number 0. The bit string is
|
||||
given by its first bit and its length in bits.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __BITS__
|
||||
#define __BITS__
|
||||
|
||||
#include "ammunition_limits.h"
|
||||
|
||||
/* This macro value returns bit vlaue (0 or 1) with given bit
|
||||
displacement (0, 1, ...). The macro has side effects! Value of
|
||||
`bit_displacement' must be nonegative and can be greater than
|
||||
CHAR_BIT. */
|
||||
|
||||
#define BIT(start_byte, bit_displacement) \
|
||||
((((const char *) (start_byte))[(bit_displacement) / CHAR_BIT] >> \
|
||||
(CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & \
|
||||
1)
|
||||
|
||||
/* This macro value sets up new value (must be `0' or `1') of a given
|
||||
bit (bit displacement starts with 0). The macro has side effects!
|
||||
Value of `bit_displacement' must be nonegative and can be greater
|
||||
than CHAR_BIT. */
|
||||
|
||||
#define SET_BIT(start_byte, bit_displacement, bit) \
|
||||
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] = \
|
||||
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] & \
|
||||
~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT))) | \
|
||||
((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
|
||||
|
||||
int ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
|
||||
int bit_length);
|
||||
void ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
|
||||
int bit_length);
|
||||
void ammunition_bit_string_copy(void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length);
|
||||
void ammunition_bit_string_move(void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length);
|
||||
int ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
|
||||
const void *str2, int bit_displacement2,
|
||||
int bit_length);
|
||||
|
||||
#endif /* #ifndef __BITS__ */
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Include section
|
||||
*/
|
||||
|
||||
#include "ammunition_stdio.h"
|
||||
#include "ammunition_stdlib.h"
|
||||
#include "ammunition_string.h"
|
||||
|
||||
/*
|
||||
Standard library functions
|
||||
*/
|
||||
|
||||
// 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 char
|
||||
ammunition_isdigit(unsigned char c) {
|
||||
if ((c >= '0') & (c <= '9'))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_isspace(int c) {
|
||||
return (c == ' ') | (c == '\t') | (c == '\n') | (c == '\r');
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void *
|
||||
ammunition_memcpy(void *dest, const void *src, size_t size) {
|
||||
size_t i;
|
||||
__pragma_loopbound(2, 6);
|
||||
for (i = 0; i < size; i++)
|
||||
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void *
|
||||
ammunition_memset(void *s, int c, size_t n) {
|
||||
size_t i;
|
||||
__pragma_loopbound(0, 4);
|
||||
for (i = 0; i < n; i++)
|
||||
((unsigned char *) s)[i] = (unsigned char) c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_memcmp(const void *mem1, const void *mem2, size_t size) {
|
||||
const unsigned char *p1 = (const unsigned char *) mem1,
|
||||
*p2 = (const unsigned char *) mem2;
|
||||
__pragma_loopbound(0, 4);
|
||||
while (size--)
|
||||
if (*p1 != *p2)
|
||||
return (*p1 - *p2);
|
||||
else
|
||||
p1++, p2++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The following function is an analog of standard C function
|
||||
`memmove'. The function returns the first operand. */
|
||||
|
||||
__attribute__((always_inline)) static inline void *
|
||||
ammunition_memmove(void *s1, const void *s2, size_t n) {
|
||||
int i;
|
||||
|
||||
if (((char *) s1 < (char *) s2 && (char *) s1 + n <= (char *) s2) ||
|
||||
((char *) s2 < (char *) s1 && (char *) s2 + n <= (char *) s1))
|
||||
return (void *) ammunition_memcpy(s1, s2, n);
|
||||
if ((char *) s1 < (char *) s2 && (char *) s1 + n > (char *) s2) {
|
||||
__pragma_loopbound(0, 4);
|
||||
for (i = 0; (size_t) i < n; i++)
|
||||
((char *) s1)[i] = ((char *) s2)[i];
|
||||
} else {
|
||||
__pragma_loopbound(0, 4);
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
((char *) s1)[i] = ((char *) s2)[i];
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_strcmp(const char *str1, const char *str2) {
|
||||
__pragma_loopbound(1, 11);
|
||||
while (*str1 && (*str1 == *str2))
|
||||
str1++, str2++;
|
||||
return *(const unsigned char *) str1 - *(const unsigned char *) str2;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_atoi(const char *str) {
|
||||
int result = 0;
|
||||
int sign = (str[0] == '-' ? -1 : 1);
|
||||
|
||||
int readingPos = 0;
|
||||
if (str[0] == '-' || str[0] == '+')
|
||||
readingPos++;
|
||||
__pragma_loopbound(1, 7);
|
||||
do {
|
||||
result *= 10;
|
||||
result += str[readingPos++] - 48;
|
||||
} while (str[readingPos] != 0);
|
||||
|
||||
return sign * result;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_sprintf_d(char *s, int number) {
|
||||
/* How many decimal digits do we need? */
|
||||
char digits = 0;
|
||||
unsigned char writePos = 0;
|
||||
long long copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
digits++;
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
writePos = digits;
|
||||
if (number < 0) {
|
||||
writePos++;
|
||||
s[0] = '-';
|
||||
}
|
||||
s[writePos] = 0;
|
||||
|
||||
copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
s[--writePos] =
|
||||
48 + ((copyOfNumber >= 0 ? copyOfNumber : -copyOfNumber) % 10);
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
return digits + (number < 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_sprintf_u(char *s, unsigned int number) {
|
||||
/* How many decimal digits do we need? */
|
||||
char digits = 0;
|
||||
unsigned char writePos = 0;
|
||||
unsigned long long copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
digits++;
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
writePos = digits;
|
||||
s[writePos] = 0;
|
||||
|
||||
copyOfNumber = number;
|
||||
__pragma_loopbound(1, 10);
|
||||
do {
|
||||
s[--writePos] = 48 + (copyOfNumber % 10);
|
||||
copyOfNumber /= 10;
|
||||
} while (copyOfNumber != 0);
|
||||
|
||||
return digits;
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
|
||||
#ifndef AMMUNITION_LIMITS_H
|
||||
#define AMMUNITION_LIMITS_H
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
#define UCHAR_MAX 255
|
||||
#endif
|
||||
#ifndef SCHAR_MAX
|
||||
#define SCHAR_MAX 127
|
||||
#endif
|
||||
#ifndef SCHAR_MIN
|
||||
#define SCHAR_MIN (-128)
|
||||
#endif
|
||||
#ifndef USHRT_MAX
|
||||
#define USHRT_MAX 65535
|
||||
#endif
|
||||
#ifndef SHRT_MAX
|
||||
#define SHRT_MAX 32767
|
||||
#endif
|
||||
#ifndef SHRT_MIN
|
||||
#define SHRT_MIN (-32768)
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
#define UINT_MAX (INT_MAX * 2U + 1)
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 2147483647
|
||||
#endif
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef AMMUNITION_LIMITS_H */
|
||||
@ -0,0 +1,11 @@
|
||||
|
||||
#ifndef AMMUNITION_STDIO_H
|
||||
#define AMMUNITION_STDIO_H
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_sprintf_d(char *s, int number);
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_sprintf_u(char *s, unsigned int number);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,8 @@
|
||||
|
||||
#ifndef AMMUNITION_STDLIB_H
|
||||
#define AMMUNITION_STDLIB_H
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_atoi(const char *str);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,22 @@
|
||||
|
||||
#ifndef AMMUNITION_STRING_H
|
||||
#define AMMUNITION_STRING_H
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
/*
|
||||
Forward declaration of functions
|
||||
*/
|
||||
|
||||
__attribute__((always_inline)) static inline void *
|
||||
ammunition_memcpy(void *, const void *, size_t);
|
||||
__attribute__((always_inline)) static inline void *
|
||||
ammunition_memset(void *, int, size_t);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_memcmp(const void *mem1, const void *mem2, size_t size);
|
||||
__attribute__((always_inline)) static inline void *
|
||||
ammunition_memmove(void *s1, const void *s2, size_t n);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_strcmp(const char *str1, const char *str2);
|
||||
|
||||
#endif /* AMMUNITION_STRING_H */
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,139 @@
|
||||
/*
|
||||
FILE NAME: arithm.h
|
||||
|
||||
TITLE: Include file of package for arbitrary precision integer
|
||||
arithmetic
|
||||
|
||||
DESCRIPTION: This header file contains ANSI C prototype definitions of
|
||||
the package functions and definitions of external
|
||||
variable of the package and C++ classes for arbitrary
|
||||
precision integer arithmetic.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ARITHMETIC__
|
||||
#define __ARITHMETIC__
|
||||
|
||||
#include "ammunition_limits.h"
|
||||
|
||||
/* This page contains definitions of variables and macros common for
|
||||
all package functions. */
|
||||
|
||||
/* The value of macro is suggested to be maximum length of integer operands
|
||||
The length of use integers should be not greater than this value. */
|
||||
|
||||
#define MAX_INTEGER_OPERAND_SIZE 128
|
||||
|
||||
/* The following macro value is sign of integer number (0 or 1) given
|
||||
as macro parameter. */
|
||||
|
||||
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
|
||||
|
||||
extern int ammunition_overflow_bit;
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_add_unsigned_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_add_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_subtract_unsigned_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_subtract_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_multiply_unsigned_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_multiply_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_divide_unsigned_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_divide_integer(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_unsigned_integer_remainder(int size, const void *op1,
|
||||
const void *op2, void *result);
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_unsigned_integer_shift_right(int size, const void *operand, int bits,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_integer_shift_right(int size, const void *operand, int bits,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_integer_shift_left(int size, const void *operand, int bits,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_unsigned_integer_shift_left(int size, const void *operand, int bits,
|
||||
void *result);
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_integer_or(int size, const void *op1, const void *op2, void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_unsigned_integer_or(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_integer_and(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_unsigned_integer_and(int size, const void *op1, const void *op2,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_integer_not(int size, const void *operand, void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_unsigned_integer_not(int size, const void *operand, void *result);
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_eq_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_eq_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_ne_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_ne_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_gt_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_gt_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_lt_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_lt_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_ge_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_ge_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_le_unsigned_integer(int size, const void *op1, const void *op2);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_le_integer(int size, const void *op1, const void *op2);
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_change_unsigned_integer_size(int operand_size, const void *operand,
|
||||
int result_size, void *result);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_change_integer_size(int operand_size, const void *operand,
|
||||
int result_size, void *result);
|
||||
|
||||
__attribute__((always_inline)) static inline char *
|
||||
ammunition_unsigned_integer_to_string(int size, const void *operand,
|
||||
char *result);
|
||||
__attribute__((always_inline)) static inline char *
|
||||
ammunition_integer_to_string(int size, const void *operand, char *result);
|
||||
|
||||
__attribute__((always_inline)) static inline char *
|
||||
ammunition_unsigned_integer_from_string(int size, const char *operand,
|
||||
void *result);
|
||||
__attribute__((always_inline)) static inline char *
|
||||
ammunition_integer_from_string(int size, const char *operand, void *result);
|
||||
|
||||
__attribute__((always_inline)) static inline char
|
||||
ammunition_isdigit(unsigned char c);
|
||||
__attribute__((always_inline)) static inline int ammunition_isspace(int c);
|
||||
|
||||
#endif /* #ifndef __ARITHMETIC__ */
|
||||
@ -0,0 +1,305 @@
|
||||
/*
|
||||
|
||||
FILE NAME: bits.c
|
||||
|
||||
TITLE: Package for work with bits
|
||||
|
||||
DESCRIPTION: This file implements functions of the package for work
|
||||
with bit strings. A bit is given by address (start address) of
|
||||
byte from which counting bits starts and its displacement which
|
||||
is any non negative number of bit from the start address. The
|
||||
most significant bit of the start address byte has number 0.
|
||||
The bit string is given by its first bit and its length in
|
||||
bits.
|
||||
|
||||
*/
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
/* This function determines that given bit string contains only zero
|
||||
bits. The function retruns TRUE if all bits of given bit string
|
||||
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. */
|
||||
|
||||
// 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 int
|
||||
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
|
||||
int bit_length) {
|
||||
const unsigned char *current_byte = (unsigned const char *) start_byte;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return 1 /* TRUE */;
|
||||
current_byte += bit_displacement / CHAR_BIT;
|
||||
bit_displacement %= CHAR_BIT;
|
||||
if (bit_length < CHAR_BIT - bit_displacement)
|
||||
return (((*current_byte << bit_displacement) &
|
||||
(UCHAR_MAX << (CHAR_BIT - bit_length))) &
|
||||
UCHAR_MAX) == 0;
|
||||
else if (bit_displacement != 0) {
|
||||
if (((*current_byte << bit_displacement) & UCHAR_MAX) != 0)
|
||||
return 0 /* FALSE */;
|
||||
current_byte += 1;
|
||||
bit_length -= CHAR_BIT - bit_displacement;
|
||||
}
|
||||
__pragma_loopbound(0, 7);
|
||||
while (bit_length >= CHAR_BIT) {
|
||||
if (*current_byte != 0)
|
||||
return 0 /* FALSE */;
|
||||
current_byte++;
|
||||
bit_length -= CHAR_BIT;
|
||||
}
|
||||
if (bit_length > 0 && (*current_byte >> (CHAR_BIT - bit_length)) != 0)
|
||||
return 0 /* FALSE */;
|
||||
return 1 /* TRUE */;
|
||||
}
|
||||
|
||||
/* This function sets up new value of all bits of given bit string.
|
||||
This function is analog of standard C function `memset'. Value of
|
||||
`bit_displacement' must be non-negative and can be greater than
|
||||
CHAR_BIT. */
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
|
||||
int bit_length) {
|
||||
unsigned char *current_byte = (unsigned char *) start_byte;
|
||||
unsigned char filling_byte;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
bit = bit != 0; /* 1 or 0 */
|
||||
filling_byte = (bit ? UCHAR_MAX : 0);
|
||||
current_byte += bit_displacement / CHAR_BIT;
|
||||
bit_displacement %= CHAR_BIT;
|
||||
if (bit_displacement != 0) {
|
||||
mask = UCHAR_MAX << (CHAR_BIT - bit_displacement);
|
||||
if (bit_length < CHAR_BIT - bit_displacement)
|
||||
mask |= UCHAR_MAX >> (bit_displacement + bit_length);
|
||||
*current_byte = (*current_byte & mask) | (filling_byte & ~mask);
|
||||
current_byte += 1;
|
||||
bit_length -= CHAR_BIT - bit_displacement;
|
||||
}
|
||||
__pragma_loopbound(0, 8);
|
||||
while (bit_length >= CHAR_BIT) {
|
||||
*current_byte = filling_byte;
|
||||
current_byte++;
|
||||
bit_length -= CHAR_BIT;
|
||||
}
|
||||
if (bit_length > 0)
|
||||
*current_byte =
|
||||
(*current_byte & ~(UCHAR_MAX << (CHAR_BIT - bit_length))) |
|
||||
(filling_byte & (UCHAR_MAX << (CHAR_BIT - bit_length)));
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string. This
|
||||
function is analog of standard C function `memcpy'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string must
|
||||
be non-overlapped. */
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
|
||||
int from_bit_displacement, int bit_length) {
|
||||
unsigned char *current_to_byte = (unsigned char *) to;
|
||||
const unsigned char *current_from_byte = (unsigned const char *) from;
|
||||
int byte;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT;
|
||||
to_bit_displacement %= CHAR_BIT;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT;
|
||||
from_bit_displacement %= CHAR_BIT;
|
||||
__pragma_loopbound(0, 7);
|
||||
while (1) {
|
||||
byte =
|
||||
(((*current_from_byte << from_bit_displacement) & UCHAR_MAX) |
|
||||
(from_bit_displacement != 0 &&
|
||||
bit_length > (CHAR_BIT - from_bit_displacement)
|
||||
? current_from_byte[1] >> (CHAR_BIT - from_bit_displacement)
|
||||
: 0));
|
||||
if (bit_length <= CHAR_BIT)
|
||||
break;
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
*current_to_byte = (*current_to_byte &
|
||||
(UCHAR_MAX << (CHAR_BIT - to_bit_displacement))) |
|
||||
(byte >> to_bit_displacement);
|
||||
if (to_bit_displacement != 0)
|
||||
current_to_byte[1] =
|
||||
(current_to_byte[1] & (UCHAR_MAX >> to_bit_displacement)) |
|
||||
(byte << (CHAR_BIT - to_bit_displacement));
|
||||
bit_length -= CHAR_BIT;
|
||||
current_from_byte++;
|
||||
current_to_byte++;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
mask = ((UCHAR_MAX << (CHAR_BIT - to_bit_displacement)) |
|
||||
(UCHAR_MAX >> (to_bit_displacement + bit_length)));
|
||||
*current_to_byte =
|
||||
(*current_to_byte & mask) | ((byte >> to_bit_displacement) & ~mask);
|
||||
bit_length -= CHAR_BIT - to_bit_displacement;
|
||||
if (bit_length > 0)
|
||||
current_to_byte[1] = (current_to_byte[1] & (UCHAR_MAX >> bit_length)) |
|
||||
((byte << (CHAR_BIT - to_bit_displacement)) &
|
||||
(UCHAR_MAX << (CHAR_BIT - bit_length)));
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string. Copying
|
||||
starts with the last bits of the bit strings. This function is
|
||||
used by function `bit_string_move'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string must
|
||||
be non-overlapped. */
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_reverse_bit_string_copy(void *to, int to_bit_displacement,
|
||||
const void *from, int from_bit_displacement,
|
||||
int bit_length) {
|
||||
unsigned char *current_to_byte = (unsigned char *) to;
|
||||
const unsigned char *current_from_byte = (unsigned const char *) from;
|
||||
int byte;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
to_bit_displacement += bit_length - 1;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
|
||||
to_bit_displacement %= CHAR_BIT; /* last bit */
|
||||
from_bit_displacement += bit_length - 1;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
|
||||
from_bit_displacement %= CHAR_BIT; /* last bit */
|
||||
__pragma_loopbound(0, 7);
|
||||
while (1) {
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
byte = ((*current_from_byte >> (CHAR_BIT - 1 - from_bit_displacement)) |
|
||||
((from_bit_displacement != CHAR_BIT - 1 &&
|
||||
bit_length > from_bit_displacement + 1
|
||||
? current_from_byte[-1] << (from_bit_displacement + 1)
|
||||
: 0) &
|
||||
UCHAR_MAX));
|
||||
if (bit_length <= CHAR_BIT)
|
||||
break;
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
*current_to_byte =
|
||||
(*current_to_byte & (UCHAR_MAX >> (to_bit_displacement + 1))) |
|
||||
(byte << (CHAR_BIT - 1 - to_bit_displacement));
|
||||
if (to_bit_displacement != CHAR_BIT - 1)
|
||||
current_to_byte[-1] =
|
||||
(current_to_byte[-1] &
|
||||
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement))) |
|
||||
(byte >> (to_bit_displacement + 1));
|
||||
bit_length -= CHAR_BIT;
|
||||
current_from_byte--;
|
||||
current_to_byte--;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its
|
||||
value is less than word bit size. */
|
||||
mask = ((UCHAR_MAX >> (to_bit_displacement + 1)) |
|
||||
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement + bit_length)));
|
||||
*current_to_byte = (*current_to_byte & mask) |
|
||||
((byte << (CHAR_BIT - 1 - to_bit_displacement)) & ~mask);
|
||||
bit_length -= to_bit_displacement + 1;
|
||||
if (bit_length > 0)
|
||||
current_to_byte[-1] =
|
||||
(current_to_byte[-1] & (UCHAR_MAX << bit_length)) |
|
||||
(byte >> (to_bit_displacement + 1) &
|
||||
(UCHAR_MAX >> (CHAR_BIT - bit_length)));
|
||||
}
|
||||
|
||||
/* This function copys a bit string to another bit string with the aid
|
||||
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
|
||||
function is analog of standard C function `memmove'. Values of
|
||||
`to_bit_displacement' and `from_bit_displacement' must be
|
||||
non-negative and can be greater than CHAR_BIT. The bit string can
|
||||
be overlapped. */
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
|
||||
int from_bit_displacement, int bit_length) {
|
||||
unsigned char *current_to_byte = (unsigned char *) to;
|
||||
const unsigned char *current_from_byte = (unsigned const char *) from;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return;
|
||||
current_to_byte += to_bit_displacement / CHAR_BIT;
|
||||
to_bit_displacement %= CHAR_BIT;
|
||||
current_from_byte += from_bit_displacement / CHAR_BIT;
|
||||
from_bit_displacement %= CHAR_BIT;
|
||||
if (current_from_byte > current_to_byte ||
|
||||
(current_from_byte == current_to_byte &&
|
||||
from_bit_displacement > to_bit_displacement))
|
||||
ammunition_bit_string_copy(current_to_byte, to_bit_displacement,
|
||||
current_from_byte, from_bit_displacement,
|
||||
bit_length);
|
||||
else
|
||||
ammunition_reverse_bit_string_copy(current_to_byte, to_bit_displacement,
|
||||
current_from_byte,
|
||||
from_bit_displacement, bit_length);
|
||||
}
|
||||
|
||||
/* This function compares bit strings. This function is analog of
|
||||
standard C function `memcmp'. The function returns 0 if the bit
|
||||
strings are equal, 1 if the first bit string is greater than the
|
||||
second, -1 if the first bit string is less than the first. Values
|
||||
of `bit_displacement1' and `bit_displacement2' must be non-negative
|
||||
and can be greater than CHAR_BIT. */
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
|
||||
const void *str2, int bit_displacement2,
|
||||
int bit_length) {
|
||||
const unsigned char *current_byte1 = (unsigned const char *) str1;
|
||||
const unsigned char *current_byte2 = (unsigned const char *) str2;
|
||||
int byte1;
|
||||
int byte2;
|
||||
int mask;
|
||||
|
||||
if (bit_length <= 0)
|
||||
return 0;
|
||||
current_byte1 += bit_displacement1 / CHAR_BIT;
|
||||
bit_displacement1 %= CHAR_BIT;
|
||||
current_byte2 += bit_displacement2 / CHAR_BIT;
|
||||
bit_displacement2 %= CHAR_BIT;
|
||||
__pragma_loopbound(0, 7);
|
||||
while (1) {
|
||||
byte1 = (((*current_byte1 << bit_displacement1) & UCHAR_MAX) |
|
||||
(bit_displacement1 != 0
|
||||
/* Shift is correct when to_bit_displacement == 0
|
||||
because its value is less than word bit size. */
|
||||
&& bit_length > CHAR_BIT - bit_displacement1
|
||||
? current_byte1[1] >> (CHAR_BIT - bit_displacement1)
|
||||
: 0));
|
||||
byte2 = (((*current_byte2 << bit_displacement2) & UCHAR_MAX) |
|
||||
(bit_displacement2 != 0 &&
|
||||
bit_length > CHAR_BIT - bit_displacement2
|
||||
? current_byte2[1] >> (CHAR_BIT - bit_displacement2)
|
||||
: 0));
|
||||
if (bit_length <= CHAR_BIT)
|
||||
break;
|
||||
if (byte1 > byte2)
|
||||
return 1;
|
||||
else if (byte1 < byte2)
|
||||
return -1;
|
||||
bit_length -= CHAR_BIT;
|
||||
current_byte2++;
|
||||
current_byte1++;
|
||||
}
|
||||
/* Shift is correct when to_bit_displacement == 0 because its value
|
||||
is less than word bit size. */
|
||||
mask = UCHAR_MAX << (CHAR_BIT - bit_length);
|
||||
if ((byte1 & mask) > (byte2 & mask))
|
||||
return 1;
|
||||
else if ((byte1 & mask) < (byte2 & mask))
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
FILE NAME: bits.h
|
||||
|
||||
TITLE: Include file of package for work with bits
|
||||
|
||||
DESCRIPTION:
|
||||
This is header file contains macros and the ANSI C prototype
|
||||
definitions for the package for work with bits and bit strings
|
||||
and C++ class for work with bits and bit strings. A bit is
|
||||
given by address (start address) of byte from which counting
|
||||
bits starts and its displacement which is any non negative
|
||||
number of bit from the start address. The most significant bit
|
||||
of the start address byte has number 0. The bit string is
|
||||
given by its first bit and its length in bits.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __BITS__
|
||||
#define __BITS__
|
||||
|
||||
#include "ammunition_limits.h"
|
||||
|
||||
/* This macro value returns bit vlaue (0 or 1) with given bit
|
||||
displacement (0, 1, ...). The macro has side effects! Value of
|
||||
`bit_displacement' must be nonegative and can be greater than
|
||||
CHAR_BIT. */
|
||||
|
||||
#define BIT(start_byte, bit_displacement) \
|
||||
((((const char *) (start_byte))[(bit_displacement) / CHAR_BIT] >> \
|
||||
(CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & \
|
||||
1)
|
||||
|
||||
/* This macro value sets up new value (must be `0' or `1') of a given
|
||||
bit (bit displacement starts with 0). The macro has side effects!
|
||||
Value of `bit_displacement' must be nonegative and can be greater
|
||||
than CHAR_BIT. */
|
||||
|
||||
#define SET_BIT(start_byte, bit_displacement, bit) \
|
||||
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] = \
|
||||
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] & \
|
||||
~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT))) | \
|
||||
((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
|
||||
int bit_length);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
|
||||
int bit_length);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
|
||||
int from_bit_displacement, int bit_length);
|
||||
__attribute__((always_inline)) static inline void
|
||||
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
|
||||
int from_bit_displacement, int bit_length);
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
|
||||
const void *str2, int bit_displacement2,
|
||||
int bit_length);
|
||||
|
||||
#endif /* #ifndef __BITS__ */
|
||||
Reference in New Issue
Block a user