Move Jerry's libc to jerry-libc directory.
This commit is contained in:
@@ -1,770 +0,0 @@
|
||||
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jerry printf implementation
|
||||
*/
|
||||
|
||||
#include "jrt.h"
|
||||
#include "jerry-libc.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* printf's length type
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_NONE, /**< (none) */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_HH, /**< hh */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_H, /**< h */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_L, /**< l */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_LL, /**< ll */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_J, /**< j */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_Z, /**< z */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_T, /**< t */
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL /**< L */
|
||||
} libc_printf_arg_length_type_t;
|
||||
|
||||
/**
|
||||
* printf's flags mask
|
||||
*/
|
||||
typedef uint8_t libc_printf_arg_flags_mask_t;
|
||||
|
||||
/**
|
||||
* Left justification of field's contents
|
||||
*/
|
||||
#define LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY (1 << 0)
|
||||
|
||||
/**
|
||||
* Force print of number's sign
|
||||
*/
|
||||
#define LIBC_PRINTF_ARG_FLAG_PRINT_SIGN (1 << 1)
|
||||
|
||||
/**
|
||||
* If no sign is printed, print space before value
|
||||
*/
|
||||
#define LIBC_PRINTF_ARG_FLAG_SPACE (1 << 2)
|
||||
|
||||
/**
|
||||
* For o, x, X preceed value with 0, 0x or 0X for non-zero values.
|
||||
*/
|
||||
#define LIBC_PRINTF_ARG_FLAG_SHARP (1 << 3)
|
||||
|
||||
/**
|
||||
* Left-pad field with zeroes instead of spaces
|
||||
*/
|
||||
#define LIBC_PRINTF_ARG_FLAG_ZERO_PADDING (1 << 4)
|
||||
|
||||
/**
|
||||
* printf helper function that outputs a char
|
||||
*/
|
||||
static void
|
||||
libc_printf_putchar (_FILE *stream, /**< stream pointer */
|
||||
char character) /**< character */
|
||||
{
|
||||
__fwrite (&character, 1, sizeof (character), stream);
|
||||
} /* libc_printf_putchar */
|
||||
|
||||
/**
|
||||
* printf helper function that outputs justified string
|
||||
*/
|
||||
static void
|
||||
libc_printf_justified_string_output (_FILE *stream, /**< stream pointer */
|
||||
const char *string_p, /**< string */
|
||||
size_t width, /**< minimum field width */
|
||||
bool is_left_justify, /**< justify to left (true) or right (false) */
|
||||
bool is_zero_padding) /**< left-pad with zeroes (true) or spaces (false) */
|
||||
{
|
||||
const size_t str_length = __strlen (string_p);
|
||||
|
||||
size_t outputted_length = 0;
|
||||
|
||||
if (!is_left_justify)
|
||||
{
|
||||
char padding_char = is_zero_padding ? '0' : ' ';
|
||||
|
||||
while (outputted_length + str_length < width)
|
||||
{
|
||||
libc_printf_putchar (stream, padding_char);
|
||||
outputted_length++;
|
||||
}
|
||||
}
|
||||
|
||||
__fwrite (string_p, 1, str_length * sizeof (*string_p), stream);
|
||||
outputted_length += str_length;
|
||||
|
||||
if (is_left_justify)
|
||||
{
|
||||
while (outputted_length < width)
|
||||
{
|
||||
libc_printf_putchar (stream, ' ');
|
||||
outputted_length++;
|
||||
}
|
||||
}
|
||||
} /* libc_printf_justified_string_output */
|
||||
|
||||
/**
|
||||
* printf helper function that converts unsigned integer to string
|
||||
*/
|
||||
static char*
|
||||
libc_printf_uint_to_string (uintmax_t value, /**< integer value */
|
||||
char *buffer_p, /**< buffer for output string */
|
||||
size_t buffer_size, /**< buffer size */
|
||||
const char *alphabet, /**< alphabet used for digits */
|
||||
uint32_t radix) /**< radix */
|
||||
{
|
||||
char *str_buffer_end = buffer_p + buffer_size;
|
||||
char *str_p = str_buffer_end;
|
||||
*--str_p = '\0';
|
||||
|
||||
JERRY_ASSERT(radix >= 2);
|
||||
|
||||
if ((radix & (radix - 1)) != 0)
|
||||
{
|
||||
/*
|
||||
* Radix is not power of 2. Only 32-bit numbers are supported in this mode.
|
||||
*/
|
||||
JERRY_ASSERT((value >> 32) == 0);
|
||||
|
||||
uint32_t value_lo = (uint32_t) value;
|
||||
|
||||
while (value_lo != 0)
|
||||
{
|
||||
JERRY_ASSERT (str_p != buffer_p);
|
||||
|
||||
*--str_p = alphabet[ value_lo % radix ];
|
||||
value_lo /= radix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t shift = 0;
|
||||
while (!(radix & (1u << shift)))
|
||||
{
|
||||
shift++;
|
||||
|
||||
JERRY_ASSERT(shift <= 32);
|
||||
}
|
||||
|
||||
uint32_t value_lo = (uint32_t) value;
|
||||
uint32_t value_hi = (uint32_t) (value >> 32);
|
||||
|
||||
while (value_lo != 0
|
||||
|| value_hi != 0)
|
||||
{
|
||||
JERRY_ASSERT (str_p != buffer_p);
|
||||
|
||||
*--str_p = alphabet[ value_lo & (radix - 1) ];
|
||||
value_lo >>= shift;
|
||||
value_lo += (value_hi & (radix - 1)) << (32 - shift);
|
||||
value_hi >>= shift;
|
||||
}
|
||||
}
|
||||
|
||||
if (*str_p == '\0')
|
||||
{
|
||||
*--str_p = '0';
|
||||
}
|
||||
|
||||
JERRY_ASSERT(str_p >= buffer_p && str_p < str_buffer_end);
|
||||
|
||||
return str_p;
|
||||
} /* libc_printf_uint_to_string */
|
||||
|
||||
/**
|
||||
* printf helper function that prints d and i arguments
|
||||
*
|
||||
* @return updated va_list
|
||||
*/
|
||||
static void
|
||||
libc_printf_write_d_i (_FILE *stream, /**< stream pointer */
|
||||
va_list* args_list_p, /**< args' list */
|
||||
libc_printf_arg_flags_mask_t flags, /**< field's flags */
|
||||
libc_printf_arg_length_type_t length, /**< field's length type */
|
||||
uint32_t width) /**< minimum field width to output */
|
||||
{
|
||||
JERRY_ASSERT((flags & LIBC_PRINTF_ARG_FLAG_SHARP) == 0);
|
||||
|
||||
bool is_signed = true;
|
||||
uintmax_t value = 0;
|
||||
|
||||
/* true - positive, false - negative */
|
||||
bool sign = true;
|
||||
const uintmax_t value_sign_mask = ((uintmax_t)1) << (sizeof (value) * JERRY_BITSINBYTE - 1);
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_NONE:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, int);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_HH:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, int); /* char is promoted to int */
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_H:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, int); /* short int is promoted to int */
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_L:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, long int);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_LL:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, long long int);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_J:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, intmax_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_Z:
|
||||
{
|
||||
is_signed = false;
|
||||
value = (uintmax_t)va_arg (*args_list_p, size_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_T:
|
||||
{
|
||||
is_signed = false;
|
||||
value = (uintmax_t)va_arg (*args_list_p, ptrdiff_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL:
|
||||
{
|
||||
JERRY_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
if (is_signed)
|
||||
{
|
||||
sign = ((value & value_sign_mask) == 0);
|
||||
|
||||
if (!sign)
|
||||
{
|
||||
value = (uintmax_t) (-value);
|
||||
}
|
||||
}
|
||||
|
||||
char str_buffer[ 32 ];
|
||||
char *string_p = libc_printf_uint_to_string (value,
|
||||
str_buffer,
|
||||
sizeof (str_buffer),
|
||||
"0123456789",
|
||||
10);
|
||||
|
||||
if (!sign
|
||||
|| (flags & LIBC_PRINTF_ARG_FLAG_PRINT_SIGN))
|
||||
{
|
||||
JERRY_ASSERT (string_p > str_buffer);
|
||||
*--string_p = (sign ? '+' : '-');
|
||||
}
|
||||
else if (flags & LIBC_PRINTF_ARG_FLAG_SPACE)
|
||||
{
|
||||
/* no sign and space flag, printing one space */
|
||||
|
||||
libc_printf_putchar (stream, ' ');
|
||||
if (width > 0)
|
||||
{
|
||||
width--;
|
||||
}
|
||||
}
|
||||
|
||||
libc_printf_justified_string_output (stream,
|
||||
string_p,
|
||||
width,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
|
||||
} /** libc_printf_write_d_i */
|
||||
|
||||
/**
|
||||
* printf helper function that prints d and i arguments
|
||||
*
|
||||
* @return updated va_list
|
||||
*/
|
||||
static void
|
||||
libc_printf_write_u_o_x_X(_FILE *stream, /**< stream pointer */
|
||||
char specifier, /**< specifier (u, o, x, X) */
|
||||
va_list* args_list_p, /**< args' list */
|
||||
libc_printf_arg_flags_mask_t flags, /**< field's flags */
|
||||
libc_printf_arg_length_type_t length, /**< field's length type */
|
||||
uint32_t width) /**< minimum field width to output */
|
||||
{
|
||||
uintmax_t value = 0;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_NONE:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, unsigned int);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_HH:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, unsigned int); /* char is promoted to int */
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_H:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, unsigned int); /* short int is promoted to int */
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_L:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, unsigned long int);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_LL:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, unsigned long long int);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_J:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, uintmax_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_Z:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, size_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_T:
|
||||
{
|
||||
value = (uintmax_t)va_arg (*args_list_p, ptrdiff_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL:
|
||||
{
|
||||
JERRY_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & LIBC_PRINTF_ARG_FLAG_SHARP)
|
||||
{
|
||||
if (value != 0 && specifier != 'u')
|
||||
{
|
||||
libc_printf_putchar (stream, '0');
|
||||
|
||||
if (specifier == 'x')
|
||||
{
|
||||
libc_printf_putchar (stream, 'x');
|
||||
}
|
||||
else if (specifier == 'X')
|
||||
{
|
||||
libc_printf_putchar (stream, 'X');
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT(specifier == 'o');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t radix = 10;
|
||||
const char *alphabet;
|
||||
|
||||
switch (specifier)
|
||||
{
|
||||
case 'u':
|
||||
{
|
||||
alphabet = "0123456789";
|
||||
radix = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
alphabet = "01234567";
|
||||
radix = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'x':
|
||||
{
|
||||
alphabet = "0123456789abcdef";
|
||||
radix = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'X':
|
||||
{
|
||||
alphabet = "0123456789ABCDEF";
|
||||
radix = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
char str_buffer[ 32 ];
|
||||
const char *string_p = libc_printf_uint_to_string (value,
|
||||
str_buffer,
|
||||
sizeof (str_buffer),
|
||||
alphabet,
|
||||
radix);
|
||||
|
||||
if (flags & LIBC_PRINTF_ARG_FLAG_PRINT_SIGN)
|
||||
{
|
||||
/* printing sign */
|
||||
|
||||
libc_printf_putchar (stream, '+');
|
||||
if (width > 0)
|
||||
{
|
||||
width--;
|
||||
}
|
||||
}
|
||||
else if (flags & LIBC_PRINTF_ARG_FLAG_SPACE)
|
||||
{
|
||||
/* no sign and space flag, printing one space */
|
||||
|
||||
libc_printf_putchar (stream, ' ');
|
||||
if (width > 0)
|
||||
{
|
||||
width--;
|
||||
}
|
||||
}
|
||||
|
||||
libc_printf_justified_string_output (stream,
|
||||
string_p,
|
||||
width,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
|
||||
} /** libc_printf_write_u_o_x_X */
|
||||
|
||||
/**
|
||||
* vfprintf
|
||||
*
|
||||
* @return number of characters printed
|
||||
*/
|
||||
static int
|
||||
__vfprintf (_FILE *stream, /**< stream pointer */
|
||||
const char *format, /**< format string */
|
||||
va_list args) /**< arguments */
|
||||
{
|
||||
va_list args_copy;
|
||||
|
||||
va_copy (args_copy, args);
|
||||
|
||||
const char *format_iter_p = format;
|
||||
|
||||
while (*format_iter_p)
|
||||
{
|
||||
if (*format_iter_p != '%')
|
||||
{
|
||||
libc_printf_putchar (stream, *format_iter_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
libc_printf_arg_flags_mask_t flags = 0;
|
||||
uint32_t width = 0;
|
||||
libc_printf_arg_length_type_t length = LIBC_PRINTF_ARG_LENGTH_TYPE_NONE;
|
||||
|
||||
while (true)
|
||||
{
|
||||
format_iter_p++;
|
||||
|
||||
if (*format_iter_p == '-')
|
||||
{
|
||||
flags |= LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY;
|
||||
}
|
||||
else if (*format_iter_p == '+')
|
||||
{
|
||||
flags |= LIBC_PRINTF_ARG_FLAG_PRINT_SIGN;
|
||||
}
|
||||
else if (*format_iter_p == ' ')
|
||||
{
|
||||
flags |= LIBC_PRINTF_ARG_FLAG_SPACE;
|
||||
}
|
||||
else if (*format_iter_p == '#')
|
||||
{
|
||||
flags |= LIBC_PRINTF_ARG_FLAG_SHARP;
|
||||
}
|
||||
else if (*format_iter_p == '0')
|
||||
{
|
||||
flags |= LIBC_PRINTF_ARG_FLAG_ZERO_PADDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*format_iter_p == '*')
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
|
||||
// If there is a number, recognize it as field width
|
||||
while (*format_iter_p >= '0' && *format_iter_p <= '9')
|
||||
{
|
||||
width = width * 10u + (uint32_t) (*format_iter_p - '0');
|
||||
|
||||
format_iter_p++;
|
||||
}
|
||||
|
||||
if (*format_iter_p == '.')
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
|
||||
switch (*format_iter_p)
|
||||
{
|
||||
case 'h':
|
||||
{
|
||||
format_iter_p++;
|
||||
if (*format_iter_p == 'h')
|
||||
{
|
||||
format_iter_p++;
|
||||
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_HH;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_H;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
format_iter_p++;
|
||||
if (*format_iter_p == 'l')
|
||||
{
|
||||
format_iter_p++;
|
||||
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_LL;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_L;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'j':
|
||||
{
|
||||
format_iter_p++;
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_J;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'z':
|
||||
{
|
||||
format_iter_p++;
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_Z;
|
||||
break;
|
||||
}
|
||||
|
||||
case 't':
|
||||
{
|
||||
format_iter_p++;
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_T;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
format_iter_p++;
|
||||
length = LIBC_PRINTF_ARG_LENGTH_TYPE_HIGHL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (*format_iter_p)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
libc_printf_write_d_i (stream, &args_copy, flags, length, width);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'u':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
libc_printf_write_u_o_x_X(stream, *format_iter_p, &args_copy, flags, length, width);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'a':
|
||||
case 'A':
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
if (length & LIBC_PRINTF_ARG_LENGTH_TYPE_L)
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[2] =
|
||||
{
|
||||
(char)va_arg (args_copy, int), /* char is promoted to int */
|
||||
'\0'
|
||||
};
|
||||
|
||||
libc_printf_justified_string_output (stream,
|
||||
str,
|
||||
width,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
if (length & LIBC_PRINTF_ARG_LENGTH_TYPE_L)
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
else
|
||||
{
|
||||
char *str_p = va_arg (args_copy, char*);
|
||||
|
||||
libc_printf_justified_string_output (stream,
|
||||
str_p,
|
||||
width,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_LEFT_JUSTIFY,
|
||||
flags & LIBC_PRINTF_ARG_FLAG_ZERO_PADDING);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
va_list args_copy2;
|
||||
va_copy (args_copy2, args_copy);
|
||||
void *value = va_arg (args_copy2, void*);
|
||||
va_end (args_copy2);
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
__printf ("(nil)");
|
||||
}
|
||||
else
|
||||
{
|
||||
libc_printf_write_u_o_x_X(stream,
|
||||
'x',
|
||||
&args_copy,
|
||||
flags | LIBC_PRINTF_ARG_FLAG_SHARP,
|
||||
LIBC_PRINTF_ARG_LENGTH_TYPE_Z,
|
||||
width);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
format_iter_p++;
|
||||
}
|
||||
|
||||
va_end (args_copy);
|
||||
|
||||
return 0;
|
||||
} /* __vfprintf */
|
||||
|
||||
/**
|
||||
* fprintf
|
||||
*
|
||||
* @return number of characters printed
|
||||
*/
|
||||
int
|
||||
__fprintf (_FILE *stream, /**< stream pointer */
|
||||
const char *format, /**< format string */
|
||||
...) /**< parameters' values */
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
|
||||
int ret = __vfprintf (stream, format, args);
|
||||
|
||||
va_end (args);
|
||||
|
||||
return ret;
|
||||
} /* __fprintf */
|
||||
|
||||
/**
|
||||
* printf
|
||||
*
|
||||
* @return number of characters printed
|
||||
*/
|
||||
int
|
||||
__printf (const char *format, /**< format string */
|
||||
...) /**< parameters' values */
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
|
||||
int ret = __vfprintf (LIBC_STDOUT, format, args);
|
||||
|
||||
va_end (args);
|
||||
|
||||
return ret;
|
||||
} /* __printf */
|
||||
|
||||
@@ -1,372 +0,0 @@
|
||||
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jerry libc's common functions implementation
|
||||
*/
|
||||
|
||||
#include "jerry-libc.h"
|
||||
|
||||
/**
|
||||
* memcpy alias to __memcpy (for compiler usage)
|
||||
*/
|
||||
extern "C" void *memcpy (void *s1, const void*s2, size_t n);
|
||||
|
||||
/**
|
||||
* memset alias to __memset (for compiler usage)
|
||||
*/
|
||||
extern "C" void *memset (void *s, int c, size_t n);
|
||||
|
||||
/**
|
||||
* memmove alias to __memmove (for compiler usage)
|
||||
*/
|
||||
extern "C" void *memmove (void *s1, const void*s2, size_t n);
|
||||
|
||||
#ifdef __GNUC__
|
||||
/*
|
||||
* Making GCC not to replace:
|
||||
* - __memcpy -> call to memcpy;
|
||||
* - __memset -> call to memset;
|
||||
* - __memmove -> call to memmove.
|
||||
*/
|
||||
CALL_PRAGMA(GCC diagnostic push)
|
||||
CALL_PRAGMA(GCC diagnostic ignored "-Wpragmas")
|
||||
CALL_PRAGMA(GCC push_options)
|
||||
CALL_PRAGMA(GCC optimize ("-fno-tree-loop-distribute-patterns"))
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
/**
|
||||
* memcpy alias to __memcpy (for compiler usage)
|
||||
*/
|
||||
void* __used
|
||||
memcpy (void *s1, /**< destination */
|
||||
const void* s2, /**< source */
|
||||
size_t n) /**< bytes number */
|
||||
{
|
||||
return __memcpy (s1, s2, n);
|
||||
} /* memcpy */
|
||||
|
||||
/**
|
||||
* memset alias to __memset (for compiler usage)
|
||||
*/
|
||||
void* __used
|
||||
memset (void *s, /**< area to set values in */
|
||||
int c, /**< value to set */
|
||||
size_t n) /**< area size */
|
||||
{
|
||||
return __memset (s, c, n);
|
||||
} /* memset */
|
||||
|
||||
/**
|
||||
* memmove alias to __memmove (for compiler usage)
|
||||
*/
|
||||
void* __used
|
||||
memmove (void *s1, /**< destination*/
|
||||
const void*s2, /**< source */
|
||||
size_t n) /**< area size */
|
||||
{
|
||||
return __memmove (s1, s2, n);
|
||||
} /* memmove */
|
||||
|
||||
#ifdef __GNUC__
|
||||
CALL_PRAGMA(GCC pop_options)
|
||||
CALL_PRAGMA(GCC diagnostic pop)
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
/**
|
||||
* Unreachable stubs for routines that are never called,
|
||||
* but referenced from third-party libraries.
|
||||
*/
|
||||
#define JRT_UNREACHABLE_STUB_FOR(...) \
|
||||
extern "C" __VA_ARGS__; \
|
||||
__used __VA_ARGS__ \
|
||||
{ \
|
||||
JERRY_UNREACHABLE (); \
|
||||
}
|
||||
|
||||
JRT_UNREACHABLE_STUB_FOR(void abort (void))
|
||||
JRT_UNREACHABLE_STUB_FOR(int raise (int sig_no __unused))
|
||||
|
||||
#undef JRT_UNREACHABLE_STUB_FOR
|
||||
|
||||
/**
|
||||
* memset
|
||||
*
|
||||
* @return @s
|
||||
*/
|
||||
void*
|
||||
__memset (void *s, /**< area to set values in */
|
||||
int c, /**< value to set */
|
||||
size_t n) /**< area size */
|
||||
{
|
||||
uint8_t *area_p = (uint8_t *) s;
|
||||
for (size_t index = 0; index < n; index++)
|
||||
{
|
||||
area_p[ index ] = (uint8_t) c;
|
||||
}
|
||||
|
||||
return s;
|
||||
} /* __memset */
|
||||
|
||||
/**
|
||||
* memcmp
|
||||
*
|
||||
* @return 0, if areas are equal;
|
||||
* -1, if first area's content is lexicographically less, than second area's content;
|
||||
* 1, otherwise
|
||||
*/
|
||||
int
|
||||
__memcmp (const void *s1, /**< first area */
|
||||
const void *s2, /**< second area */
|
||||
size_t n) /**< area size */
|
||||
{
|
||||
const uint8_t *area1_p = (uint8_t *) s1, *area2_p = (uint8_t *) s2;
|
||||
for (size_t index = 0; index < n; index++)
|
||||
{
|
||||
if (area1_p[ index ] < area2_p[ index ])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (area1_p[ index ] > area2_p[ index ])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /* __memcmp */
|
||||
|
||||
/**
|
||||
* memcpy
|
||||
*/
|
||||
void *
|
||||
__memcpy (void *s1, /**< destination */
|
||||
const void *s2, /**< source */
|
||||
size_t n) /**< bytes number */
|
||||
{
|
||||
uint8_t *area1_p = (uint8_t *) s1;
|
||||
const uint8_t *area2_p = (const uint8_t *) s2;
|
||||
|
||||
for (size_t index = 0; index < n; index++)
|
||||
{
|
||||
area1_p[ index ] = area2_p[ index ];
|
||||
}
|
||||
|
||||
return s1;
|
||||
} /* __memcpy */
|
||||
|
||||
/**
|
||||
* memmove
|
||||
*
|
||||
* @return the dest pointer's value
|
||||
*/
|
||||
void *
|
||||
__memmove (void *s1, /**< destination */
|
||||
const void *s2, /**< source */
|
||||
size_t n) /**< bytes number */
|
||||
{
|
||||
uint8_t *dest_p = (uint8_t *) s1;
|
||||
const uint8_t *src_p = (const uint8_t *) s2;
|
||||
|
||||
if (dest_p < src_p)
|
||||
{ /* from begin to end */
|
||||
for (size_t index = 0; index < n; index++)
|
||||
{
|
||||
dest_p[ index ] = src_p[ index ];
|
||||
}
|
||||
}
|
||||
else if (dest_p > src_p)
|
||||
{ /* from end to begin */
|
||||
for (size_t index = 1; index <= n; index++)
|
||||
{
|
||||
dest_p[ n - index ] = src_p[ n - index ];
|
||||
}
|
||||
}
|
||||
|
||||
return s1;
|
||||
} /* __memmove */
|
||||
|
||||
/** Compare two strings. return an integer less than, equal to, or greater than zero
|
||||
if s1 is found, respectively, to be less than, to match, or be greater than s2. */
|
||||
int
|
||||
__strcmp (const char *s1, const char *s2)
|
||||
{
|
||||
size_t i;
|
||||
if (s1 == NULL)
|
||||
{
|
||||
if (s2 != NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (s2 == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; s1[i]; i++)
|
||||
{
|
||||
if (s1[i] > s2[i])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (s1[i] < s2[i])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (s2[i])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Compare two strings. return an integer less than, equal to, or greater than zero
|
||||
if the first n character of s1 is found, respectively, to be less than, to match,
|
||||
or be greater than the first n character of s2. */
|
||||
int
|
||||
__strncmp (const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
if (s1 == NULL)
|
||||
{
|
||||
if (s2 != NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (s2 == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (s1[i] > s2[i])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (s1[i] < s2[i])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Copy a string. At most n bytes of src are copied. Warning: If there is no
|
||||
null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
|
||||
@return a pointer to the destination string dest. */
|
||||
char *
|
||||
__strncpy (char *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
dest[i] = src[i];
|
||||
if (src[i] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/** Calculate the length of a string. */
|
||||
size_t
|
||||
__strlen (const char *s)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; s[i]; i++)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/** Checks for white-space characters. In the "C" and "POSIX" locales, these are: space,
|
||||
form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). */
|
||||
int
|
||||
__isspace (int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\v':
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks for an uppercase letter. */
|
||||
int
|
||||
__isupper (int c)
|
||||
{
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
/** Checks for an lowercase letter. */
|
||||
int
|
||||
__islower (int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
/** Checks for an alphabetic character.
|
||||
In the standard "C" locale, it is equivalent to (isupper (c) || islower (c)). */
|
||||
int
|
||||
__isalpha (int c)
|
||||
{
|
||||
return __isupper (c) || __islower (c);
|
||||
}
|
||||
|
||||
/** Checks for a digit (0 through 9). */
|
||||
int
|
||||
__isdigit (int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
/** checks for a hexadecimal digits, that is, one of
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F. */
|
||||
int
|
||||
__isxdigit (int c)
|
||||
{
|
||||
return __isdigit (c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jerry libc declarations
|
||||
*/
|
||||
#ifndef JERRY_LIBC_H
|
||||
#define JERRY_LIBC_H
|
||||
|
||||
#include "jrt.h"
|
||||
|
||||
typedef void _FILE;
|
||||
|
||||
/**
|
||||
* stdin file descriptor
|
||||
*/
|
||||
#define LIBC_STDIN (_FILE*)0
|
||||
|
||||
/**
|
||||
* stdout file descriptor
|
||||
*/
|
||||
#define LIBC_STDOUT (_FILE*)1
|
||||
|
||||
/**
|
||||
* stderr file descriptor
|
||||
*/
|
||||
#define LIBC_STDERR (_FILE*)2
|
||||
|
||||
extern void* __memset (void *s, int c, size_t n);
|
||||
extern int __memcmp (const void *s1, const void *s2, size_t n);
|
||||
extern void* __memcpy (void *s1, const void *s2, size_t n);
|
||||
extern void* __memmove (void *dest, const void *src, size_t n);
|
||||
extern int __printf (const char *format, ...);
|
||||
extern int __putchar (int);
|
||||
extern "C" void __noreturn __exit (int);
|
||||
|
||||
extern int __strcmp (const char *, const char *);
|
||||
extern int __strncmp (const char *, const char *, size_t);
|
||||
extern char* __strncpy (char *, const char *, size_t);
|
||||
extern float __strtof (const char *, char **);
|
||||
extern size_t __strlen (const char *);
|
||||
|
||||
extern int __isspace (int);
|
||||
extern int __isupper (int);
|
||||
extern int __islower (int);
|
||||
extern int __isalpha (int);
|
||||
extern int __isdigit (int);
|
||||
extern int __isxdigit (int);
|
||||
|
||||
/**
|
||||
* 'whence' argument of __fseek that identifies position
|
||||
* the 'offset' argument is added to.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
__SEEK_SET, /**< relative to begin of file */
|
||||
__SEEK_CUR, /**< relative to current position */
|
||||
__SEEK_END /**< relative to end of file */
|
||||
} _whence_t;
|
||||
|
||||
extern _FILE* __fopen (const char *, const char *);
|
||||
extern int __fclose (_FILE *);
|
||||
extern int __fseek (_FILE *, long offset, _whence_t);
|
||||
extern long __ftell (_FILE *);
|
||||
extern void __rewind (_FILE *);
|
||||
extern size_t __fread (void *, size_t, size_t, _FILE *);
|
||||
extern size_t __fwrite (const void *, size_t, size_t, _FILE *);
|
||||
extern int __fprintf (_FILE *, const char *, ...);
|
||||
|
||||
extern void jrt_set_mem_limits (size_t data_size, size_t stack_size);
|
||||
|
||||
#define HUGE_VAL (1e37f)
|
||||
|
||||
#endif /* JERRY_LIBC_H */
|
||||
@@ -1,79 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ASM_ARM_H
|
||||
#define ASM_ARM_H
|
||||
|
||||
/*
|
||||
* mov syscall_no (%r0) -> %r7
|
||||
* mov arg1 (%r1) -> %r0
|
||||
* svc #0
|
||||
*/
|
||||
#define SYSCALL_1 \
|
||||
push {r4-r12, lr}; \
|
||||
\
|
||||
mov r7, r0; \
|
||||
mov r0, r1; \
|
||||
\
|
||||
svc #0; \
|
||||
\
|
||||
pop {r4-r12, pc};
|
||||
|
||||
/*
|
||||
* mov syscall_no (%r0) -> %r7
|
||||
* mov arg1 (%r1) -> %r0
|
||||
* mov arg2 (%r2) -> %r1
|
||||
* svc #0
|
||||
*/
|
||||
#define SYSCALL_2 \
|
||||
push {r4-r12, lr}; \
|
||||
\
|
||||
mov r7, r0; \
|
||||
mov r0, r1; \
|
||||
mov r1, r2; \
|
||||
\
|
||||
svc #0; \
|
||||
\
|
||||
pop {r4-r12, pc};
|
||||
|
||||
/*
|
||||
* mov syscall_no (%r0) -> %r7
|
||||
* mov arg1 (%r1) -> %r0
|
||||
* mov arg2 (%r2) -> %r1
|
||||
* mov arg3 (%r3) -> %r2
|
||||
* svc #0
|
||||
*/
|
||||
#define SYSCALL_3 \
|
||||
push {r4-r12, lr}; \
|
||||
\
|
||||
mov r7, r0; \
|
||||
mov r0, r1; \
|
||||
mov r1, r2; \
|
||||
mov r2, r3; \
|
||||
\
|
||||
svc #0; \
|
||||
\
|
||||
pop {r4-r12, pc};
|
||||
|
||||
#define _START \
|
||||
ldr r0, [sp, #0]; \
|
||||
add r1, sp, #4; \
|
||||
bl main; \
|
||||
\
|
||||
bl __exit; \
|
||||
1: \
|
||||
b 1b
|
||||
|
||||
#endif /* !ASM_ARM_H */
|
||||
@@ -1,69 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ASM_X64_H
|
||||
#define ASM_X64_H
|
||||
|
||||
/*
|
||||
* mov syscall_no (%rdi) -> %rax
|
||||
* mov arg1 (%rsi) -> %rdi
|
||||
* syscall
|
||||
*/
|
||||
#define SYSCALL_1 \
|
||||
mov %rdi, %rax; \
|
||||
mov %rsi, %rdi; \
|
||||
syscall; \
|
||||
ret;
|
||||
|
||||
/*
|
||||
* mov syscall_no (%rdi) -> %rax
|
||||
* mov arg1 (%rsi) -> %rdi
|
||||
* mov arg2 (%rdx) -> %rsi
|
||||
* syscall
|
||||
*/
|
||||
#define SYSCALL_2 \
|
||||
mov %rdi, %rax; \
|
||||
mov %rsi, %rdi; \
|
||||
mov %rdx, %rsi; \
|
||||
syscall; \
|
||||
ret;
|
||||
|
||||
/*
|
||||
* mov syscall_no (%rdi) -> %rax
|
||||
* mov arg1 (%rsi) -> %rdi
|
||||
* mov arg2 (%rdx) -> %rsi
|
||||
* mov arg3 (%rcx) -> %rdx
|
||||
* syscall
|
||||
*/
|
||||
#define SYSCALL_3 \
|
||||
mov %rdi, %rax; \
|
||||
mov %rsi, %rdi; \
|
||||
mov %rdx, %rsi; \
|
||||
mov %rcx, %rdx; \
|
||||
syscall; \
|
||||
ret;
|
||||
|
||||
#define _START \
|
||||
mov (%rsp), %rdi; \
|
||||
mov %rsp, %rsi; \
|
||||
add $8, %rsi; \
|
||||
callq main; \
|
||||
\
|
||||
mov %rax, %rdi; \
|
||||
callq __exit; \
|
||||
1: \
|
||||
jmp 1b
|
||||
|
||||
#endif /* !ASM_X64_H */
|
||||
@@ -1,72 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ASM_X86_H
|
||||
#define ASM_X86_H
|
||||
|
||||
FIXME(Implement x86 ABI);
|
||||
#error "Not implemented"
|
||||
|
||||
/*
|
||||
* mov syscall_no -> %rax
|
||||
* mov arg1 -> %rdi
|
||||
* syscall
|
||||
* mov %rax -> ret
|
||||
*/
|
||||
#define SYSCALL_1 (syscall_no, arg1, ret) \
|
||||
__asm ("syscall" \
|
||||
: "=a" (ret) \
|
||||
: "a" (syscall_no), "D" (arg1) \
|
||||
: "rcx", "r11");
|
||||
|
||||
/*
|
||||
* mov syscall_no -> %rax
|
||||
* mov arg1 -> %rdi
|
||||
* mov arg2 -> %rsi
|
||||
* syscall
|
||||
* mov %rax -> ret
|
||||
*/
|
||||
#define SYSCALL_2 (syscall_no, arg1, arg2, ret) \
|
||||
__asm ("syscall" \
|
||||
: "=a" (ret) \
|
||||
: "a" (syscall_no), "D" (arg1), "S" (arg2) \
|
||||
: "rcx", "r11");
|
||||
|
||||
/*
|
||||
* mov syscall_no -> %rax
|
||||
* mov arg1 -> %rdi
|
||||
* mov arg2 -> %rsi
|
||||
* mov arg3 -> %rdx
|
||||
* syscall
|
||||
* mov %rax -> ret
|
||||
*/
|
||||
#define SYSCALL_3 (syscall_no, arg1, arg2, arg3, ret) \
|
||||
__asm ("syscall" \
|
||||
: "=a" (ret) \
|
||||
: "a" (syscall_no), "D" (arg1), "S" (arg2), "d" (arg3) \
|
||||
: "rcx", "r11");
|
||||
|
||||
#define _START \
|
||||
mov (%rsp), %rdi; \
|
||||
mov %rsp, %rsi; \
|
||||
add $8, %rsi; \
|
||||
callq main; \
|
||||
\
|
||||
mov %rax, %rdi; \
|
||||
callq __exit; \
|
||||
1: \
|
||||
jmp 1b
|
||||
|
||||
#endif /* !ASM_X86_H */
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifdef __TARGET_HOST_x64
|
||||
# include "asm_x64.h"
|
||||
#elif defined (__TARGET_HOST_x86)
|
||||
# include "asm_x86.h"
|
||||
#elif defined (__TARGET_HOST_ARMv7)
|
||||
# include "asm_arm.h"
|
||||
#else /* !__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7 */
|
||||
# error "!__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7"
|
||||
#endif /* !__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7 */
|
||||
|
||||
.global _start
|
||||
.type _start, %function
|
||||
_start:
|
||||
_START
|
||||
.size _start, . - _start
|
||||
|
||||
.global syscall_1_asm
|
||||
.type syscall_1_asm, %function
|
||||
syscall_1_asm:
|
||||
SYSCALL_1
|
||||
.size syscall_1_asm, . - syscall_1_asm
|
||||
|
||||
.global syscall_2_asm
|
||||
.type syscall_2_asm, %function
|
||||
syscall_2_asm:
|
||||
SYSCALL_2
|
||||
.size syscall_2_asm, . - syscall_2_asm
|
||||
|
||||
.global syscall_3_asm
|
||||
.type syscall_3_asm, %function
|
||||
syscall_3_asm:
|
||||
SYSCALL_3
|
||||
.size syscall_3_asm, . - syscall_3_asm
|
||||
|
||||
@@ -1,400 +0,0 @@
|
||||
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jerry libc platform-specific functions linux implementation
|
||||
*/
|
||||
|
||||
#include "jrt.h"
|
||||
#include "jerry-libc.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
#ifdef __TARGET_HOST_x64
|
||||
# include "asm_x64.h"
|
||||
#elif defined (__TARGET_HOST_x86)
|
||||
# include "asm_x86.h"
|
||||
#elif defined (__TARGET_HOST_ARMv7)
|
||||
# include "asm_arm.h"
|
||||
#else /* !__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7 */
|
||||
# error "!__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7 "
|
||||
#endif /* !__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7 */
|
||||
|
||||
FIXME(Rename __unused)
|
||||
#undef __unused
|
||||
|
||||
#include <syscall.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
FIXME (/* Include linux/fs.h */)
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
/**
|
||||
* Exit program with ERR_SYSCALL if syscall_ret_val is negative
|
||||
*/
|
||||
#define LIBC_EXIT_ON_ERROR(syscall_ret_val) \
|
||||
if (unlikely ((syscall_ret_val) < 0)) \
|
||||
{ \
|
||||
jerry_fatal (ERR_SYSCALL); \
|
||||
}
|
||||
|
||||
static long int syscall_1 (long int syscall_no, long int arg1);
|
||||
static long int syscall_2 (long int syscall_no, long int arg1, long int arg2);
|
||||
static long int syscall_3 (long int syscall_no, long int arg1, long int arg2, long int arg3);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern long int syscall_1_asm (long int syscall_no, long int arg1);
|
||||
extern long int syscall_2_asm (long int syscall_no, long int arg1, long int arg2);
|
||||
extern long int syscall_3_asm (long int syscall_no, long int arg1, long int arg2, long int arg3);
|
||||
}
|
||||
|
||||
/**
|
||||
* System call with one argument.
|
||||
*
|
||||
* @return syscall's return value
|
||||
*/
|
||||
static __noinline long int
|
||||
syscall_1 (long int syscall_no, /**< syscall number */
|
||||
long int arg1) /**< argument */
|
||||
{
|
||||
long int ret = syscall_1_asm (syscall_no, arg1);
|
||||
|
||||
LIBC_EXIT_ON_ERROR(ret);
|
||||
|
||||
return ret;
|
||||
} /* syscall_1 */
|
||||
|
||||
/**
|
||||
* System call with two arguments.
|
||||
*
|
||||
* @return syscall's return value
|
||||
*/
|
||||
static __noinline long int
|
||||
syscall_2 (long int syscall_no, /**< syscall number */
|
||||
long int arg1, /**< first argument */
|
||||
long int arg2) /**< second argument */
|
||||
{
|
||||
long int ret = syscall_2_asm (syscall_no, arg1, arg2);
|
||||
|
||||
LIBC_EXIT_ON_ERROR(ret);
|
||||
|
||||
return ret;
|
||||
} /* syscall_2 */
|
||||
|
||||
/**
|
||||
* System call with three arguments.
|
||||
*
|
||||
* @return syscall's return value
|
||||
*/
|
||||
static __noinline long int
|
||||
syscall_3 (long int syscall_no, /**< syscall number */
|
||||
long int arg1, /**< first argument */
|
||||
long int arg2, /**< second argument */
|
||||
long int arg3) /**< third argument */
|
||||
{
|
||||
long int ret = syscall_3_asm (syscall_no, arg1, arg2, arg3);
|
||||
|
||||
LIBC_EXIT_ON_ERROR(ret);
|
||||
|
||||
return ret;
|
||||
} /* syscall_3 */
|
||||
|
||||
/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */
|
||||
int
|
||||
__putchar (int c)
|
||||
{
|
||||
__fwrite (&c, 1, sizeof (char), LIBC_STDOUT);
|
||||
|
||||
return c;
|
||||
} /* __putchar */
|
||||
|
||||
/**
|
||||
* Exit - cause normal process termination with specified status code
|
||||
*/
|
||||
void __noreturn
|
||||
__exit (int status) /**< status code */
|
||||
{
|
||||
syscall_1 (__NR_close, (long int)LIBC_STDIN);
|
||||
syscall_1 (__NR_close, (long int)LIBC_STDOUT);
|
||||
syscall_1 (__NR_close, (long int)LIBC_STDERR);
|
||||
|
||||
syscall_1 (__NR_exit_group, status);
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* unreachable */
|
||||
}
|
||||
} /* __exit */
|
||||
|
||||
/**
|
||||
* fopen
|
||||
*
|
||||
* @return _FILE pointer - upon successful completion,
|
||||
* NULL - otherwise
|
||||
*/
|
||||
_FILE*
|
||||
__fopen (const char *path, /**< file path */
|
||||
const char *mode) /**< file open mode */
|
||||
{
|
||||
bool may_read = false;
|
||||
bool may_write = false;
|
||||
bool truncate = false;
|
||||
bool create_if_not_exist = false;
|
||||
bool position_at_end = false;
|
||||
|
||||
JERRY_ASSERT(path != NULL && mode != NULL);
|
||||
JERRY_ASSERT(mode[1] == '+' || mode[1] == '\0');
|
||||
|
||||
switch (mode[0])
|
||||
{
|
||||
case 'r':
|
||||
{
|
||||
may_read = true;
|
||||
may_write = (mode[1] == '+');
|
||||
break;
|
||||
}
|
||||
case 'w':
|
||||
{
|
||||
may_write = true;
|
||||
truncate = true;
|
||||
create_if_not_exist = true;
|
||||
may_read = (mode[1] == '+');
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
{
|
||||
may_write = true;
|
||||
position_at_end = true;
|
||||
create_if_not_exist = true;
|
||||
if (mode[1] == '+')
|
||||
{
|
||||
/* Not supported */
|
||||
JERRY_UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
int access = S_IRUSR | S_IWUSR;
|
||||
if (may_read && !may_write)
|
||||
{
|
||||
flags = O_RDONLY;
|
||||
}
|
||||
else if (!may_read && may_write)
|
||||
{
|
||||
flags = O_WRONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT(may_read && may_write);
|
||||
|
||||
flags = O_RDWR;
|
||||
}
|
||||
|
||||
if (truncate)
|
||||
{
|
||||
flags |= O_TRUNC;
|
||||
}
|
||||
|
||||
if (create_if_not_exist)
|
||||
{
|
||||
flags |= O_CREAT;
|
||||
}
|
||||
|
||||
if (position_at_end)
|
||||
{
|
||||
flags |= O_APPEND;
|
||||
}
|
||||
|
||||
long int ret = syscall_3 (__NR_open, (long int) path, flags, access);
|
||||
|
||||
return (void*) (uintptr_t) (ret);
|
||||
} /* __fopen */
|
||||
|
||||
/**
|
||||
* The rewind () function sets the file position indicator
|
||||
* for the stream pointed to by STREAM to the beginning of the file.
|
||||
*/
|
||||
void
|
||||
__rewind (_FILE *stream) /**< stream pointer */
|
||||
{
|
||||
syscall_3 (__NR_lseek, (long int) stream, 0, SEEK_SET);
|
||||
} /* __rewind */
|
||||
|
||||
/**
|
||||
* fclose
|
||||
*
|
||||
* @return 0 - upon successful completion,
|
||||
* non-zero value - otherwise.
|
||||
*/
|
||||
int
|
||||
__fclose (_FILE *fp) /**< stream pointer */
|
||||
{
|
||||
syscall_2 (__NR_close, (long int)fp, 0);
|
||||
|
||||
return 0;
|
||||
} /* __fclose */
|
||||
|
||||
/**
|
||||
* fseek
|
||||
*/
|
||||
int
|
||||
__fseek (_FILE * fp, /**< stream pointer */
|
||||
long offset, /**< offset */
|
||||
_whence_t whence) /**< specifies position type
|
||||
to add offset to */
|
||||
{
|
||||
int whence_real = SEEK_CUR;
|
||||
switch (whence)
|
||||
{
|
||||
case __SEEK_SET:
|
||||
{
|
||||
whence_real = SEEK_SET;
|
||||
break;
|
||||
}
|
||||
case __SEEK_CUR:
|
||||
{
|
||||
whence_real = SEEK_CUR;
|
||||
break;
|
||||
}
|
||||
case __SEEK_END:
|
||||
{
|
||||
whence_real = SEEK_END;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
syscall_3 (__NR_lseek, (long int)fp, offset, whence_real);
|
||||
|
||||
return 0;
|
||||
} /* __fseek */
|
||||
|
||||
/**
|
||||
* ftell
|
||||
*/
|
||||
long
|
||||
__ftell (_FILE * fp) /**< stream pointer */
|
||||
{
|
||||
long int ret = syscall_3 (__NR_lseek, (long int)fp, 0, SEEK_CUR);
|
||||
|
||||
return ret;
|
||||
} /* __ftell */
|
||||
|
||||
/**
|
||||
* fread
|
||||
*
|
||||
* @return number of bytes read
|
||||
*/
|
||||
size_t
|
||||
__fread (void *ptr, /**< address of buffer to read to */
|
||||
size_t size, /**< size of elements to read */
|
||||
size_t nmemb, /**< number of elements to read */
|
||||
_FILE *stream) /**< stream pointer */
|
||||
{
|
||||
long int ret;
|
||||
size_t bytes_read = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ret = syscall_3 (__NR_read,
|
||||
(long int) stream,
|
||||
(long int) ((uint8_t*) ptr + bytes_read),
|
||||
(long int) (size * nmemb - bytes_read));
|
||||
|
||||
bytes_read += (size_t)ret;
|
||||
}
|
||||
while (bytes_read != size * nmemb && ret != 0);
|
||||
|
||||
return bytes_read;
|
||||
} /* __fread */
|
||||
|
||||
/**
|
||||
* fwrite
|
||||
*
|
||||
* @return number of bytes written
|
||||
*/
|
||||
size_t
|
||||
__fwrite (const void *ptr, /**< data to write */
|
||||
size_t size, /**< size of elements to write */
|
||||
size_t nmemb, /**< number of elements */
|
||||
_FILE *stream) /**< stream pointer */
|
||||
{
|
||||
size_t bytes_written = 0;
|
||||
|
||||
do
|
||||
{
|
||||
long int ret = syscall_3 (__NR_write,
|
||||
(long int) stream,
|
||||
(long int) ((uint8_t*) ptr + bytes_written),
|
||||
(long int) (size * nmemb - bytes_written));
|
||||
|
||||
bytes_written += (size_t)ret;
|
||||
}
|
||||
while (bytes_written != size * nmemb);
|
||||
|
||||
return bytes_written;
|
||||
} /* __fwrite */
|
||||
|
||||
/**
|
||||
* Setup new memory limits
|
||||
*/
|
||||
void
|
||||
jrt_set_mem_limits (size_t data_size, /**< limit for data + bss + brk heap */
|
||||
size_t stack_size) /**< limit for stack */
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long long rlim_cur;
|
||||
unsigned long long rlim_max;
|
||||
} data_limit = { data_size, data_size };
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned long long rlim_cur;
|
||||
unsigned long long rlim_max;
|
||||
} stack_limit = { stack_size, stack_size };
|
||||
|
||||
long int ret;
|
||||
|
||||
#ifdef __TARGET_HOST_x64
|
||||
ret = syscall_2 (__NR_setrlimit, RLIMIT_DATA, (intptr_t) &data_limit);
|
||||
JERRY_ASSERT (ret == 0);
|
||||
|
||||
ret = syscall_2 (__NR_setrlimit, RLIMIT_STACK, (intptr_t) &stack_limit);
|
||||
JERRY_ASSERT (ret == 0);
|
||||
#elif defined (__TARGET_HOST_ARMv7)
|
||||
ret = syscall_3 (__NR_prlimit64, 0, RLIMIT_DATA, (intptr_t) &data_limit);
|
||||
JERRY_ASSERT (ret == 0);
|
||||
|
||||
ret = syscall_3 (__NR_prlimit64, 0, RLIMIT_STACK, (intptr_t) &stack_limit);
|
||||
JERRY_ASSERT (ret == 0);
|
||||
#elif defined (__TARGET_HOST_x86)
|
||||
# error "__TARGET_HOST_x86 case is not implemented"
|
||||
#else /* !__TARGET_HOST_x64 && !__TARGET_HOST_ARMv7 && !__TARGET_HOST_x86 */
|
||||
# error "!__TARGET_HOST_x64 && !__TARGET_HOST_ARMv7 && !__TARGET_HOST_x86"
|
||||
#endif /* !__TARGET_HOST_x64 && !__TARGET_HOST_ARMv7 && !__TARGET_HOST_x86 */
|
||||
} /* jrt_set_mem_limits */
|
||||
@@ -1,103 +0,0 @@
|
||||
/**
|
||||
* Runtime ABI for ARM architecture
|
||||
*/
|
||||
|
||||
/**
|
||||
* long long __aeabi_llsl(long long {r1, r0}, int {r2})
|
||||
*/
|
||||
.thumb_func
|
||||
.global __aeabi_llsl
|
||||
__aeabi_llsl:
|
||||
// if (r2 >= 64) goto 2f;
|
||||
cmp r2, #64
|
||||
bhs 2f
|
||||
|
||||
// if (r2 < 32) goto 1f;
|
||||
cmp r2, #32
|
||||
blo 1f
|
||||
|
||||
// r1 = (r0 << (r2 - 32));
|
||||
// r0 = 0;
|
||||
sub r2, #32
|
||||
mov r1, r0
|
||||
lsl r1, r2
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
1:
|
||||
// r1 <<= r2;
|
||||
lsl r1, r2
|
||||
|
||||
// r2 = 32 - r2;
|
||||
rsb r2, r2, #32
|
||||
|
||||
// r1 |= (r0 >> r2);
|
||||
mov r3, r0
|
||||
lsr r3, r2
|
||||
orr r1, r3
|
||||
|
||||
// r2 = 32 - r2;
|
||||
rsb r2, r2, #32
|
||||
|
||||
// r0 <<= r2;
|
||||
lsl r0, r2
|
||||
|
||||
bx lr
|
||||
|
||||
2:
|
||||
// r1 = 0;
|
||||
// r0 = 0;
|
||||
mov r1, #0
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
|
||||
/**
|
||||
* long long __aeabi_llsr(long long {r1, r0}, int {r2})
|
||||
*/
|
||||
.thumb_func
|
||||
.global __aeabi_llsr
|
||||
__aeabi_llsr:
|
||||
// if (r2 >= 64) goto 2f;
|
||||
cmp r2, #64
|
||||
bhs 2f
|
||||
|
||||
// if (r2 < 32) goto 1f;
|
||||
cmp r2, #32
|
||||
blo 1f
|
||||
|
||||
// r0 = (r1 >> (r2 - 32));
|
||||
// r1 = 0
|
||||
sub r2, #32
|
||||
mov r0, r1
|
||||
lsr r0, r2
|
||||
mov r1, #0
|
||||
|
||||
bx lr
|
||||
|
||||
1:
|
||||
// r0 >>= r2
|
||||
lsr r0, r2
|
||||
|
||||
// r0 |= r1 << (32 - r2)
|
||||
mov r3, r1
|
||||
rsb r2, r2, #32
|
||||
lsl r3, r3, r2
|
||||
orr r0, r3
|
||||
rsb r2, r2, #32
|
||||
|
||||
// r1 >>= r2
|
||||
lsr r1, r2
|
||||
|
||||
bx lr
|
||||
|
||||
2:
|
||||
// r1 = 0;
|
||||
// r0 = 0;
|
||||
mov r1, #0
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jerry libc platform-specific functions stm32f4 implementation
|
||||
*/
|
||||
|
||||
#include "jerry-libc.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
extern void __noreturn exit (int status);
|
||||
|
||||
/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */
|
||||
int
|
||||
__putchar (int c)
|
||||
{
|
||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS("putchar is not implemented for STM32F3.", c);
|
||||
} /* __putchar */
|
||||
|
||||
/** exit - cause normal process termination */
|
||||
void __noreturn
|
||||
__exit (int status __unused)
|
||||
{
|
||||
/**
|
||||
* TODO: Blink LEDs? status -> binary -> LEDs?
|
||||
*/
|
||||
|
||||
while (true)
|
||||
{
|
||||
}
|
||||
} /* __exit */
|
||||
|
||||
/**
|
||||
* fwrite
|
||||
*
|
||||
* @return number of bytes written
|
||||
*/
|
||||
size_t
|
||||
__fwrite (const void *ptr, /**< data to write */
|
||||
size_t size, /**< size of elements to write */
|
||||
size_t nmemb, /**< number of elements */
|
||||
_FILE *stream) /**< stream pointer */
|
||||
{
|
||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS("fwrite is not implemented for STM32F3.", ptr, size, nmemb, stream);
|
||||
} /* __fwrite */
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/**
|
||||
* Runtime ABI for ARM architecture
|
||||
*/
|
||||
|
||||
/**
|
||||
* long long __aeabi_llsl(long long {r1, r0}, int {r2})
|
||||
*/
|
||||
.thumb_func
|
||||
.global __aeabi_llsl
|
||||
__aeabi_llsl:
|
||||
// if (r2 >= 64) goto 2f;
|
||||
cmp r2, #64
|
||||
bhs 2f
|
||||
|
||||
// if (r2 < 32) goto 1f;
|
||||
cmp r2, #32
|
||||
blo 1f
|
||||
|
||||
// r1 = (r0 << (r2 - 32));
|
||||
// r0 = 0;
|
||||
sub r2, #32
|
||||
mov r1, r0
|
||||
lsl r1, r2
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
1:
|
||||
// r1 <<= r2;
|
||||
lsl r1, r2
|
||||
|
||||
// r2 = 32 - r2;
|
||||
rsb r2, r2, #32
|
||||
|
||||
// r1 |= (r0 >> r2);
|
||||
mov r3, r0
|
||||
lsr r3, r2
|
||||
orr r1, r3
|
||||
|
||||
// r2 = 32 - r2;
|
||||
rsb r2, r2, #32
|
||||
|
||||
// r0 <<= r2;
|
||||
lsl r0, r2
|
||||
|
||||
bx lr
|
||||
|
||||
2:
|
||||
// r1 = 0;
|
||||
// r0 = 0;
|
||||
mov r1, #0
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
|
||||
/**
|
||||
* long long __aeabi_llsr(long long {r1, r0}, int {r2})
|
||||
*/
|
||||
.thumb_func
|
||||
.global __aeabi_llsr
|
||||
__aeabi_llsr:
|
||||
// if (r2 >= 64) goto 2f;
|
||||
cmp r2, #64
|
||||
bhs 2f
|
||||
|
||||
// if (r2 < 32) goto 1f;
|
||||
cmp r2, #32
|
||||
blo 1f
|
||||
|
||||
// r0 = (r1 >> (r2 - 32));
|
||||
// r1 = 0
|
||||
sub r2, #32
|
||||
mov r0, r1
|
||||
lsr r0, r2
|
||||
mov r1, #0
|
||||
|
||||
bx lr
|
||||
|
||||
1:
|
||||
// r0 >>= r2
|
||||
lsr r0, r2
|
||||
|
||||
// r0 |= r1 << (32 - r2)
|
||||
mov r3, r1
|
||||
rsb r2, r2, #32
|
||||
lsl r3, r3, r2
|
||||
orr r0, r3
|
||||
rsb r2, r2, #32
|
||||
|
||||
// r1 >>= r2
|
||||
lsr r1, r2
|
||||
|
||||
bx lr
|
||||
|
||||
2:
|
||||
// r1 = 0;
|
||||
// r0 = 0;
|
||||
mov r1, #0
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Jerry libc platform-specific functions stm32f4 implementation
|
||||
*/
|
||||
|
||||
#include "jerry-libc.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
extern void __noreturn exit (int status);
|
||||
|
||||
/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */
|
||||
int
|
||||
__putchar (int c)
|
||||
{
|
||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS("putchar is not implemented for STM32F4.", c);
|
||||
} /* __putchar */
|
||||
|
||||
/** exit - cause normal process termination */
|
||||
void __noreturn
|
||||
__exit (int status __unused)
|
||||
{
|
||||
/**
|
||||
* TODO: Blink LEDs? status -> binary -> LEDs?
|
||||
*/
|
||||
|
||||
while (true)
|
||||
{
|
||||
}
|
||||
} /* __exit */
|
||||
|
||||
/**
|
||||
* fwrite
|
||||
*
|
||||
* @return number of bytes written
|
||||
*/
|
||||
size_t
|
||||
__fwrite (const void *ptr, /**< data to write */
|
||||
size_t size, /**< size of elements to write */
|
||||
size_t nmemb, /**< number of elements */
|
||||
_FILE *stream) /**< stream pointer */
|
||||
{
|
||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS("fwrite is not implemented for STM32F4.", ptr, size, nmemb, stream);
|
||||
} /* __fwrite */
|
||||
|
||||
Reference in New Issue
Block a user