Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,179 @@
/* Copyright 2014-2016 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
* svc #0
*/
#define SYSCALL_0 \
push {r4-r12, lr}; \
\
mov r7, r0; \
\
svc #0; \
\
pop {r4-r12, pc};
/*
* 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};
/*
* ldr argc ([sp + 0x0]) -> r0
* add argv (sp + 0x4) -> r1
*
* bl main
*
* bl exit
*
* infinite loop
*/
#define _START \
ldr r0, [sp, #0]; \
add r1, sp, #4; \
bl main; \
\
bl exit; \
1: \
b 1b
/**
* If hard-float mode:
* store s16-s31 vfp registers to buffer, pointed with r0 register,
* and increase the register on size of stored data.
*/
#ifdef __TARGET_HOST_ARMv7_HARD_FLOAT
# define _STORE_VFP_S16_S31_IF_HARD_FLOAT \
vstm r0!, {s16 - s31};
# define _LOAD_VFP_S16_S31_IF_HARD_FLOAT \
vldm r0!, {s16 - s31};
#else /* !__TARGET_HOST_ARMv7_HARD_FLOAT */
# define _STORE_VFP_S16_S31_IF_HARD_FLOAT
# define _LOAD_VFP_S16_S31_IF_HARD_FLOAT
#endif /* __TARGET_HOST_ARMv7_HARD_FLOAT */
/*
* setjmp
*
* According to procedure call standard for the ARM architecture, the following
* registers are callee-saved, and so need to be stored in context:
* - r4 - r11
* - sp
* - s16 - s31
*
* Also, we should store:
* - lr
*
* stmia {r4-r11, sp, lr} -> jmp_buf_0 (r0)!
*
* If hard-float build
* vstm {s16-s31} -> jmp_buf_32 (r0)!
*
* mov r0, #0
*
* bx lr
*/
#define _SETJMP \
stmia r0!, {r4 - r11, sp, lr}; \
\
_STORE_VFP_S16_S31_IF_HARD_FLOAT \
\
mov r0, #0; \
\
bx lr;
/*
* longjmp
*
* See also:
* _SETJMP
*
* ldmia jmp_buf_0 (r0)! -> {r4-r11, sp, lr}
*
* If hard-float build
* vldm jmp_buf_32 (r0)! -> {s16-s31}
*
* mov r1 -> r0
* cmp r0, #0
* bne 1f
* mov #1 -> r0
* 1:
*
* bx lr
*/
#define _LONGJMP \
ldmia r0!, {r4 - r11, sp, lr}; \
\
_LOAD_VFP_S16_S31_IF_HARD_FLOAT \
\
mov r0, r1; \
cmp r0, #0; \
bne 1f; \
mov r0, #1; \
1: \
\
bx lr;
#endif /* !ASM_ARM_H */

View file

@ -0,0 +1,213 @@
/* 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.
*/
#ifndef ASM_X86_H
#define ASM_X86_H
/*
* mov syscall_no -> %eax
* int $0x80
* mov %eax -> ret
*/
#define SYSCALL_0 \
push %edi; \
push %esi; \
push %ebx; \
mov 0x10 (%esp), %eax; \
int $0x80; \
pop %ebx; \
pop %esi; \
pop %edi; \
ret;
/*
* mov syscall_no -> %eax
* mov arg1 -> %ebx
* int $0x80
* mov %eax -> ret
*/
#define SYSCALL_1 \
push %edi; \
push %esi; \
push %ebx; \
mov 0x10 (%esp), %eax; \
mov 0x14 (%esp), %ebx; \
int $0x80; \
pop %ebx; \
pop %esi; \
pop %edi; \
ret;
/*
* mov syscall_no -> %eax
* mov arg1 -> %ebx
* mov arg2 -> %ecx
* int $0x80
* mov %eax -> ret
*/
#define SYSCALL_2 \
push %edi; \
push %esi; \
push %ebx; \
mov 0x10 (%esp), %eax; \
mov 0x14 (%esp), %ebx; \
mov 0x18 (%esp), %ecx; \
int $0x80; \
pop %ebx; \
pop %esi; \
pop %edi; \
ret;
/*
* mov syscall_no -> %eax
* mov arg1 -> %ebx
* mov arg2 -> %ecx
* mov arg3 -> %edx
* int $0x80
* mov %eax -> ret
*/
#define SYSCALL_3 \
push %edi; \
push %esi; \
push %ebx; \
mov 0x10 (%esp), %eax; \
mov 0x14 (%esp), %ebx; \
mov 0x18 (%esp), %ecx; \
mov 0x1c (%esp), %edx; \
int $0x80; \
pop %ebx; \
pop %esi; \
pop %edi; \
ret;
/*
* push argv (%esp + 4)
* push argc ([%esp + 0x4])
*
* call main
*
* push main_ret (%eax)
* call exit
*
* infinite loop
*/
#define _START \
mov %esp, %eax; \
add $4, %eax; \
push %eax; \
mov 0x4 (%esp), %eax; \
push %eax; \
\
call main; \
\
push %eax; \
call exit; \
\
1: \
jmp 1b
/*
* setjmp
*
* According to x86_32 System V ABI, the following registers are
* callee-saved, and so need to be stored in context:
* - %ebx
* - %esp
* - %ebp
* - %esi
* - %edi
* - x87 control word
*
* Also, we should store:
* - return address (to jump to upon longjmp)
*
* mov return_address ([%esp]) -> %eax
*
* mov env ([%esp + 0x4]) -> %edx
*
* mov %ebx -> jmp_buf_0 ([%edx + 0x0])
* mov %esp -> jmp_buf_4 ([%edx + 0x4])
* mov %ebp -> jmp_buf_8 ([%edx + 0x8])
* mov %esi -> jmp_buf_12 ([%edx + 0xc])
* mov %edi -> jmp_buf_16 ([%edx + 0x10])
* mov %eax -> jmp_buf_20 ([%edx + 0x14])
* fnstcw -> jmp_buf_24 ([%edx + 0x18])
*
* ret
*/
#define _SETJMP \
mov (%esp), %eax; \
mov 0x4 (%esp), %edx; \
\
mov %ebx, 0x00 (%edx); \
mov %esp, 0x04 (%edx); \
mov %ebp, 0x08 (%edx); \
mov %esi, 0x0c (%edx); \
mov %edi, 0x10 (%edx); \
mov %eax, 0x14 (%edx); \
fnstcw 0x18 (%edx); \
\
xor %eax, %eax; \
\
ret
/*
* longjmp
*
* See also:
* _SETJMP
*
* mov env ([%esp + 0x4]) -> %edx
* mov val ([%esp + 0x8]) -> %eax
*
* mov jmp_buf_0 ([%edx + 0x0]) -> %ebx
* mov jmp_buf_4 ([%edx + 0x8]) -> %esp
* mov jmp_buf_8 ([%edx + 0x10]) -> %ebp
* mov jmp_buf_12 ([%edx + 0x18]) -> %esi
* mov jmp_buf_16 ([%edx + 0x20]) -> %edi
* mov jmp_buf_20 ([%edx + 0x28]) -> %ecx
* fldcw jmp_buf_24 ([%edx + 0x30])
*
* mov return_address (%ecx) -> ([%esp])
*
* cmp (%eax), 0x0
* jnz 1f
* xor %eax, %eax
* 1:
*
* ret
*/
#define _LONGJMP \
mov 0x4 (%esp), %edx; \
mov 0x8 (%esp), %eax; \
\
mov 0x0 (%edx), %ebx; \
mov 0x4 (%edx), %esp; \
mov 0x8 (%edx), %ebp; \
mov 0xc (%edx), %esi; \
mov 0x10 (%edx), %edi; \
mov 0x14 (%edx), %ecx; \
fldcw 0x18 (%edx); \
\
mov %ecx, (%esp); \
\
test %eax, %eax; \
jnz 1f; \
xor %eax, %eax; \
1: \
\
ret
#endif /* !ASM_X86_H */

View file

@ -0,0 +1,188 @@
/* 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.
*/
#ifndef ASM_X64_H
#define ASM_X64_H
/*
* mov syscall_no (%rdi) -> %rax
* syscall
*/
#define SYSCALL_0 \
mov %rdi, %rax; \
syscall; \
ret;
/*
* 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;
/*
* mov argc ([%rsp]) -> %rdi
* mov argv (%rsp + 0x8) -> %rsi
*
* call main
*
* mov main_ret (%rax) -> %rdi
* call exit
*
* infinite loop
*/
#define _START \
mov (%rsp), %rdi; \
mov %rsp, %rsi; \
add $8, %rsi; \
callq main; \
\
mov %rax, %rdi; \
callq exit; \
1: \
jmp 1b
/*
* setjmp
*
* According to x86_64 System V ABI, the following registers are
* callee-saved, and so need to be stored in context:
* - %rbp
* - %rbx
* - %r12
* - %r13
* - %r14
* - %r15
* - x87 control word
*
* Also, we should store:
* - %rsp (stack pointer)
* - return address (to jump to upon longjmp)
*
* mov return_address ([%rsp]) -> %rax
*
* mov %rsp -> jmp_buf_0 ([%rdi + 0x0])
* mov %rax -> jmp_buf_8 ([%rdi + 0x8])
* mov %rbp -> jmp_buf_16 ([%rdi + 0x10])
* mov %rbx -> jmp_buf_24 ([%rdi + 0x18])
* mov %r12 -> jmp_buf_32 ([%rdi + 0x20])
* mov %r13 -> jmp_buf_40 ([%rdi + 0x28])
* mov %r14 -> jmp_buf_48 ([%rdi + 0x30])
* mov %r15 -> jmp_buf_56 ([%rdi + 0x38])
* fnstcw -> jmp_buf_64 ([%rdi + 0x40])
*
* ret
*/
#define _SETJMP \
mov (%rsp), %rax; \
\
mov %rsp, 0x00(%rdi); \
mov %rax, 0x08(%rdi); \
mov %rbp, 0x10(%rdi); \
mov %rbx, 0x18(%rdi); \
mov %r12, 0x20(%rdi); \
mov %r13, 0x28(%rdi); \
mov %r14, 0x30(%rdi); \
mov %r15, 0x38(%rdi); \
fnstcw 0x40(%rdi); \
\
xor %rax, %rax; \
\
ret;
/*
* longjmp
*
* See also:
* _SETJMP
*
* mov jmp_buf_0 ([%rdi + 0x0]) -> %rsp
* mov jmp_buf_8 ([%rdi + 0x8]) -> %rax
* mov jmp_buf_16 ([%rdi + 0x10]) -> %rbp
* mov jmp_buf_24 ([%rdi + 0x18]) -> %rbx
* mov jmp_buf_32 ([%rdi + 0x20]) -> %r12
* mov jmp_buf_40 ([%rdi + 0x28]) -> %r13
* mov jmp_buf_48 ([%rdi + 0x30]) -> %r14
* mov jmp_buf_56 ([%rdi + 0x38]) -> %r15
* fldcw jmp_buf_64 ([%rdi + 0x40])
*
* mov return_address (%rax) -> ([%rsp])
*
* mov val (%rsi) -> %rax
*
* test (%rax), (%rax)
* jnz 1f
* mov $1, %rax
* 1:
*
* ret
*/
#define _LONGJMP \
mov 0x00(%rdi), %rsp; \
mov 0x08(%rdi), %rax; \
mov 0x10(%rdi), %rbp; \
mov 0x18(%rdi), %rbx; \
mov 0x20(%rdi), %r12; \
mov 0x28(%rdi), %r13; \
mov 0x30(%rdi), %r14; \
mov 0x38(%rdi), %r15; \
fldcw 0x40(%rdi); \
\
mov %rax, (%rsp); \
\
mov %rsi, %rax; \
\
test %rax, %rax; \
jnz 1f; \
mov $1, %rax; \
1: \
\
ret
#endif /* !ASM_X64_H */

View file

@ -0,0 +1,45 @@
/* Copyright 2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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 JERRY_LIBC_ASSERT_H
#define JERRY_LIBC_ASSERT_H
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef NDEBUG
#define assert(x) \
do \
{ \
if (__builtin_expect (!(x), 0)) \
{ \
fprintf (stderr, "%s:%d: %s: Assertion `%s' failed.", __FILE__, __LINE__, __func__, #x); \
abort (); \
} \
} while (0)
#else /* NDEBUG */
#define assert(x) ((void) 0)
#endif /* !NDEBUG */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRY_LIBC_ASSERT_H */

View file

@ -0,0 +1,65 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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 JERRY_LIBC_SETJMP_H
#define JERRY_LIBC_SETJMP_H
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* Storage for context, used for nonlocal goto
*
* x86_64 (8 * 8 + 2 bytes):
* 0x00 - %rsp
* 0x08 - return address
* 0x10 - %rbp
* 0x18 - %rbx
* 0x20 - %r12
* 0x28 - %r13
* 0x30 - %r14
* 0x38 - %r15
* 0x40 - x87 control word
*
* x86_32 (6 * 4 + 2 bytes):
* - %ebx
* - %esp
* - %ebp
* - %esi
* - %edi
* - return address (to jump to upon longjmp)
* - x87 control word
*
* ARMv7 (10 * 4 + 16 * 4 bytes):
* - r4 - r11, sp, lr
* - s16 - s31 (if hardfp enabled)
*
* See also:
* setjmp, longjmp
*/
typedef uint64_t jmp_buf[14];
int setjmp (jmp_buf env);
void longjmp (jmp_buf env, int val);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRY_LIBC_SETJMP_H */

View file

@ -0,0 +1,54 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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 JERRY_LIBC_STDIO_H
#define JERRY_LIBC_STDIO_H
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* File descriptor type
*/
typedef void FILE;
/**
* Standard file descriptors
*/
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
/**
* I/O routines
*/
int vfprintf (FILE *stream, const char *format, va_list ap);
FILE *fopen (const char *path, const char *mode);
int fclose (FILE *fp);
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream);
int printf (const char *format, ...);
int fprintf (FILE *stream, const char *format, ...);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRY_LIBC_STDIO_H */

View file

@ -0,0 +1,41 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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 JERRY_LIBC_STDLIB_H
#define JERRY_LIBC_STDLIB_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* Maximum integer that could be returned by random number generator
*
* See also:
* rand
*/
#define RAND_MAX (0x7fffffffu)
void __attribute__ ((noreturn)) exit (int);
void __attribute__ ((noreturn)) abort (void);
int rand (void);
void srand (unsigned int);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRY_LIBC_STDLIB_H */

View file

@ -0,0 +1,39 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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 JERRY_LIBC_STRING_H
#define JERRY_LIBC_STRING_H
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void *memcpy (void *dest, const void *src, size_t n);
void *memset (void *s, int c, size_t n);
void *memmove (void *dest, const void *src, size_t n);
int memcmp (const void *s1, const void *s2, size_t n);
int strcmp (const char *s1, const char *s2);
int strncmp (const char *s1, const char *s2, size_t n);
char *strncpy (char *dest, const char *src, size_t n);
size_t strlen (const char *s);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRY_LIBC_STRING_H */

View file

@ -0,0 +1,48 @@
/* Copyright 2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged
*
* 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 JERRY_LIBC_TIME_H
#define JERRY_LIBC_TIME_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/**
* Time value structure
*/
struct timeval
{
unsigned long tv_sec; /**< seconds */
unsigned long tv_usec; /**< microseconds */
};
/**
* Timezone structure
*/
struct timezone
{
int tz_minuteswest; /**< minutes west of Greenwich */
int tz_dsttime; /**< type of DST correction */
};
int gettimeofday (void *tp, void *tzp);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !JERRY_LIBC_TIME_H */

View file

@ -0,0 +1,31 @@
/* Copyright 2015-2016 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 DEFS_H
#define DEFS_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/**
* Attributes
*/
#define __attr_unused___ __attribute__((unused))
#define __attr_used___ __attribute__((used))
#define __attr_noreturn___ __attribute__((noreturn))
#define __attr_noinline___ __attribute__((noinline))
#endif /* !DEFS_H */

View file

@ -0,0 +1,755 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged
*
* 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 <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "jerry-libc-defs.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';
assert (radix >= 2);
if ((radix & (radix - 1)) != 0)
{
/*
* Radix is not power of 2. Only 32-bit numbers are supported in this mode.
*/
assert ((value >> 32) == 0);
uint32_t value_lo = (uint32_t) value;
while (value_lo != 0)
{
assert (str_p != buffer_p);
*--str_p = alphabet[ value_lo % radix ];
value_lo /= radix;
}
}
else
{
uint32_t shift = 0;
while (!(radix & (1u << shift)))
{
shift++;
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)
{
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';
}
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 */
{
assert ((flags & LIBC_PRINTF_ARG_FLAG_SHARP) == 0);
bool is_signed = true;
uintmax_t value = 0;
/* true - positive, false - negative */
bool sign = true;
const size_t bits_in_byte = 8;
const uintmax_t value_sign_mask = ((uintmax_t) 1) << (sizeof (value) * bits_in_byte - 1);
switch (length)
{
case LIBC_PRINTF_ARG_LENGTH_TYPE_NONE:
case LIBC_PRINTF_ARG_LENGTH_TYPE_HH: /* char is promoted to int */
case LIBC_PRINTF_ARG_LENGTH_TYPE_H: /* short int is promoted to int */
{
value = (uintmax_t) va_arg (*args_list_p, 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:
{
assert (!"unsupported length field L");
}
}
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))
{
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;
switch (length)
{
case LIBC_PRINTF_ARG_LENGTH_TYPE_NONE:
case LIBC_PRINTF_ARG_LENGTH_TYPE_HH: /* char is promoted to int */
case LIBC_PRINTF_ARG_LENGTH_TYPE_H: /* short int is promoted to int */
{
value = (uintmax_t) va_arg (*args_list_p, unsigned 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:
{
assert (!"unsupported length field L");
return;
}
default:
{
assert (!"unexpected length field");
return;
}
}
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
{
assert (specifier == 'o');
}
}
}
uint32_t radix;
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:
{
assert (!"unexpected type field");
return;
}
}
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
*/
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 == '*')
{
assert (!"unsupported width field *");
}
// 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 == '.')
{
assert (!"unsupported precision field");
}
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':
{
assert (!"unsupported double type field");
break;
}
case 'c':
{
if (length & LIBC_PRINTF_ARG_LENGTH_TYPE_L)
{
assert (!"unsupported length field L");
}
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)
{
assert (!"unsupported length field L");
}
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':
{
assert (!"unsupported type field n");
}
}
}
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 (stdout, format, args);
va_end (args);
return ret;
} /* printf */

View file

@ -0,0 +1,283 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jerry-libc-defs.h"
/**
* State of pseudo-random number generator
*/
static uint32_t libc_random_gen_state[4] = { 1455997910, 1999515274, 1234451287, 1949149569 };
/**
* Standard file descriptors
*/
FILE *stdin = (FILE *) 0;
FILE *stdout = (FILE *) 1;
FILE *stderr = (FILE *) 2;
#ifdef __GNUC__
/*
* Making GCC not to replace:
* - memcpy -> call to memcpy;
* - memset -> call to memset;
* - memmove -> call to memmove.
*/
#define CALL_PRAGMA(x) _Pragma (#x)
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__ */
/**
* memset
*
* @return @a s
*/
void * __attr_used___ // FIXME
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;
while (n--)
{
*area_p++ = (uint8_t) c;
}
return s;
} /* memset */
/**
* memcmp
*
* @return 0, if areas are equal;
* <0, if first area's content is lexicographically less, than second area's content;
* >0, 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;
while (n--)
{
int diff = ((int) *area1_p++) - ((int) *area2_p++);
if (diff)
{
return diff;
}
}
return 0;
} /* memcmp */
/**
* memcpy
*/
void * __attr_used___ // FIXME
memcpy (void *s1, /**< destination */
const void *s2, /**< source */
size_t n) /**< bytes number */
{
uint8_t *dst_p = (uint8_t *) s1;
const uint8_t *src_p = (const uint8_t *) s2;
/* Aligned fast case. */
if (n >= 4 && !(((uintptr_t) s1) & 0x3) && !(((uintptr_t) s2) & 0x3))
{
size_t chunks = (n >> 2);
uint32_t *u32_dst_p = (uint32_t *) dst_p;
const uint32_t *u32_src_p = (const uint32_t *) src_p;
do
{
*u32_dst_p++ = *u32_src_p++;
}
while (--chunks);
n &= 0x3;
dst_p = (uint8_t *) u32_dst_p;
src_p = (const uint8_t *) u32_src_p;
}
while (n--)
{
*dst_p++ = *src_p++;
}
return s1;
} /* memcpy */
/**
* memmove
*
* @return the dest pointer's value
*/
void * __attr_used___ // FIXME
memmove (void *s1, /**< destination */
const void *s2, /**< source */
size_t n) /**< bytes number */
{
uint8_t *dest_p;
const uint8_t *src_p;
if (s1 < s2)
{ /* from begin to end */
dest_p = (uint8_t *) s1;
src_p = (const uint8_t *) s2;
while (n--)
{
*dest_p++ = *src_p++;
}
}
else if (s1 > s2)
{ /* from end to begin */
dest_p = ((uint8_t *) s1) + n - 1;
src_p = ((const uint8_t *) s2) + n - 1;
while (n--)
{
*dest_p-- = *src_p--;
}
}
return s1;
} /* memmove */
#ifdef __GNUC__
CALL_PRAGMA (GCC pop_options)
CALL_PRAGMA (GCC diagnostic pop)
#endif /* __GNUC__ */
/** 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)
{
while (1)
{
int c1 = (unsigned char) *s1++;
int c2 = (unsigned char) *s2++;
int diff = c1 - c2;
if (!c1 || diff)
{
return diff;
}
}
} /* strcmp */
/** 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)
{
while (n--)
{
int c1 = (unsigned char) *s1++;
int c2 = (unsigned char) *s2++;
int diff = c1 - c2;
if (!c1 || diff)
{
return diff;
}
}
return 0;
} /* strncmp */
/** 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 * __attr_used___ // FIXME
strncpy (char *dest, const char *src, size_t n)
{
while (n--)
{
char c = *src++;
*dest++ = c;
if (!c)
{
break;
}
}
return dest;
} /* strncpy */
/** Calculate the length of a string. */
size_t
strlen (const char *s)
{
size_t i = 0;
while (s[i])
{
i++;
}
return i;
} /* strlen */
/**
* Generate pseudo-random integer
*
* Note:
* The function implements George Marsaglia's XorShift random number generator
*
* @return integer in range [0; RAND_MAX]
*/
int
rand (void)
{
uint32_t intermediate = libc_random_gen_state[0] ^ (libc_random_gen_state[0] << 11);
intermediate ^= intermediate >> 8;
libc_random_gen_state[0] = libc_random_gen_state[1];
libc_random_gen_state[1] = libc_random_gen_state[2];
libc_random_gen_state[2] = libc_random_gen_state[3];
libc_random_gen_state[3] ^= libc_random_gen_state[3] >> 19;
libc_random_gen_state[3] ^= intermediate;
return (int) (libc_random_gen_state[3] % (RAND_MAX + 1));
} /* rand */
/**
* Initialize pseudo-random number generator with the specified seed value
*/
void
srand (unsigned int seed) /**< new seed */
{
libc_random_gen_state[0] =
libc_random_gen_state[1] =
libc_random_gen_state[2] =
libc_random_gen_state[3] = seed;
} /* srand */

View file

@ -0,0 +1,92 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged
*
* 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.
*/
#if defined (__TARGET_HOST_x64)
#include "arch/x86-64.h"
#elif defined (__TARGET_HOST_x86)
#include "arch/x86-32.h"
#elif defined (__TARGET_HOST_ARMv7)
#include "arch/arm-v7.h"
#else /* !__TARGET_HOST_x64 && !__TARGET_HOST_x86 && !__TARGET_HOST_ARMv7 */
#error "Unsupported architecture"
#endif /* __TARGET_HOST_x64 */
#if defined (__linux__)
.macro func _name
.global \_name
.type \_name, %function
\_name:
.endm
.macro endfunc _name
.size \_name, .-\_name
.endm
#elif defined (__APPLE__) && defined (__MACH__)
.macro func _name
.global \_name
\_name:
.endm
.macro endfunc _name
.endm
#else /* !__linux && !(__APPLE__ && __MACH__) */
#error "Unsupported OS"
#endif /* __linux__ */
func _start
_START
endfunc _start
func syscall_0
SYSCALL_0
endfunc syscall_0
func syscall_1
SYSCALL_1
endfunc syscall_1
func syscall_2
SYSCALL_2
endfunc syscall_2
func syscall_3
SYSCALL_3
endfunc syscall_3
/**
* setjmp (jmp_buf env)
*
* See also:
* longjmp
*
* @return 0 - if returns from direct call,
* nonzero - if returns after longjmp.
*/
func setjmp
_SETJMP
endfunc setjmp
/**
* longjmp (jmp_buf env, int val)
*
* Note:
* if val is not 0, then it would be returned from setjmp,
* otherwise - 0 would be returned.
*
* See also:
* setjmp
*/
func longjmp
_LONGJMP
endfunc longjmp

View file

@ -0,0 +1,316 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2016 University of Szeged.
*
* 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 posix implementation
*/
#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#if defined (__linux__)
#define SYSCALL_NO(NAME) __NR_ ## NAME
#elif defined (__APPLE__) && defined (__MACH__)
#define SYS_exit_group SYS_exit
#define SYSCALL_NO(NAME) SYS_ ## NAME
#else /* !__linux && !(__APPLE__ && __MACH__) */
#error "Unsupported OS"
#endif /* __linux__ */
#include "jerry-libc-defs.h"
extern long int syscall_0 (long int syscall_no);
extern long int syscall_1 (long int syscall_no, long int arg1);
extern long int syscall_2 (long int syscall_no, long int arg1, long int arg2);
extern long int syscall_3 (long int syscall_no, long int arg1, long int arg2, long int arg3);
/**
* Exit - cause normal process termination with specified status code
*/
void __attr_noreturn___ __attr_used___
exit (int status) /**< status code */
{
syscall_1 (SYSCALL_NO (close), (long int) stdin);
syscall_1 (SYSCALL_NO (close), (long int) stdout);
syscall_1 (SYSCALL_NO (close), (long int) stderr);
syscall_1 (SYSCALL_NO (exit_group), status);
while (true)
{
/* unreachable */
}
} /* exit */
/**
* Abort current process, producing an abnormal program termination.
* The function raises the SIGABRT signal.
*/
void __attr_noreturn___ __attr_used___
abort (void)
{
syscall_1 (SYSCALL_NO (close), (long int) stdin);
syscall_1 (SYSCALL_NO (close), (long int) stdout);
syscall_1 (SYSCALL_NO (close), (long int) stderr);
raise (SIGABRT);
while (true)
{
/* unreachable */
}
} /* abort */
/**
* Send a signal to the current process.
*/
int __attr_used___
raise (int sig)
{
return (int) syscall_2 (SYSCALL_NO (kill), syscall_0 (SYSCALL_NO (getpid)), sig);
} /* raise */
/**
* 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;
assert (path != NULL && mode != NULL);
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] == '+')
{
assert (!"unsupported mode a+");
}
break;
}
default:
{
assert (!"unsupported mode");
}
}
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
{
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 (SYSCALL_NO (open), (long int) path, flags, access);
return (void *) (uintptr_t) (ret);
} /* fopen */
/**
* fclose
*
* @return 0 - upon successful completion,
* non-zero value - otherwise.
*/
int
fclose (FILE *fp) /**< stream pointer */
{
syscall_2 (SYSCALL_NO (close), (long int) fp, 0);
return 0;
} /* fclose */
/**
* fread
*
* @return number of elements 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;
if (size == 0)
{
return 0;
}
do
{
ret = syscall_3 (SYSCALL_NO (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 / size;
} /* fread */
/**
* fwrite
*
* @return number of elements 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;
if (size == 0)
{
return 0;
}
do
{
long int ret = syscall_3 (SYSCALL_NO (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 / size;
} /* fwrite */
/**
* This function can get the time as well as a timezone.
*
* @return 0 if success, -1 otherwise
*/
int
gettimeofday (void *tp, /**< struct timeval */
void *tzp) /**< struct timezone */
{
return (int) syscall_2 (SYSCALL_NO (gettimeofday), (long int) tp, (long int) tzp);
} /* gettimeofday */
// FIXME
#if 0
/**
* 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;
#if defined (__TARGET_HOST_x64)
ret = syscall_2 (SYSCALL_NO (setrlimit), RLIMIT_DATA, (intptr_t) &data_limit);
assert (ret == 0);
ret = syscall_2 (SYSCALL_NO (setrlimit), RLIMIT_STACK, (intptr_t) &stack_limit);
assert (ret == 0);
#elif defined (__TARGET_HOST_ARMv7)
ret = syscall_3 (SYSCALL_NO (prlimit64), 0, RLIMIT_DATA, (intptr_t) &data_limit);
assert (ret == 0);
ret = syscall_3 (SYSCALL_NO (prlimit64), 0, RLIMIT_STACK, (intptr_t) &stack_limit);
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 */
} /* jrt_set_mem_limits */
#endif /* 0 */