Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support setjmp / longjmp in jerry-libc #194

Merged
merged 6 commits into from
Jun 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ project (Jerry CXX C ASM)
set(FLAGS_COMMON_RELEASE "-Os -nostdlib")

# Unit tests
set(FLAGS_COMMON_UNITTESTS "-O3 -nodefaultlibs")
set(FLAGS_COMMON_UNITTESTS "-O3 -nostdlib")

# Include directories
# Core interface
Expand Down Expand Up @@ -310,8 +310,9 @@ project (Jerry CXX C ASM)
add_subdirectory(plugins)

# Targets declaration
string(TOLOWER "${PLATFORM_EXT}" PLATFORM_L)

function(declare_targets_for_build_mode BUILD_MODE)
string(TOLOWER "${PLATFORM_EXT}" PLATFORM_L)
set(TARGET_NAME ${BUILD_MODE_PREFIX_${BUILD_MODE}}.${PLATFORM_L})
set(PLUGINS_TARGET_NAME ${BUILD_MODE_PREFIX_${BUILD_MODE}}.plugins.${PLATFORM_L}.lib)
set(LIBC_TARGET_NAME ${BUILD_MODE_PREFIX_${BUILD_MODE}}.jerry-libc.${PLATFORM_L}.lib)
Expand Down Expand Up @@ -424,6 +425,7 @@ project (Jerry CXX C ASM)
set(TARGET_NAME unit-${TARGET_NAME})

set(CORE_TARGET_NAME unittests.jerry-core)
set(LIBC_TARGET_NAME unittests.jerry-libc.${PLATFORM_L}.lib)
set(FDLIBM_TARGET_NAME unittests.jerry-fdlibm${SUFFIX_THIRD_PARTY_LIB})

add_executable(${TARGET_NAME} ${SOURCE_UNIT_TEST_MAIN})
Expand All @@ -432,7 +434,8 @@ project (Jerry CXX C ASM)
set_property(TARGET ${TARGET_NAME}
PROPERTY LINK_FLAGS "${COMPILE_FLAGS_JERRY} ${CXX_FLAGS_JERRY} ${FLAGS_COMMON_UNITTESTS} ${LINKER_FLAGS_COMMON}")
target_include_directories(${TARGET_NAME} PRIVATE ${INCLUDE_CORE_INTERFACE})
target_link_libraries(${TARGET_NAME} ${CORE_TARGET_NAME} ${FDLIBM_TARGET_NAME} ${PREFIX_IMPORTED_LIB}libc
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${INCLUDE_LIBC_INTERFACE})
target_link_libraries(${TARGET_NAME} ${CORE_TARGET_NAME} ${LIBC_TARGET_NAME} ${FDLIBM_TARGET_NAME}
${PREFIX_IMPORTED_LIB}libgcc ${PREFIX_IMPORTED_LIB}libgcc_eh)

add_cppcheck_target(${TARGET_NAME})
Expand Down
21 changes: 21 additions & 0 deletions build/configs/toolchain_linux_armv7l-el.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 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.

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR armv7l-el)

set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++)

set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb)
9 changes: 7 additions & 2 deletions build/configs/toolchain_linux_armv7l-hf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
# limitations under the License.

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR armv7l)
set(CMAKE_SYSTEM_PROCESSOR armv7l-hf)

set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)

set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb)
#
# Limit fpu to VFPv3 with d0-d15 registers
#
# If this is changed, setjmp / longjmp for ARMv7 should be updated accordingly
#
set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb -mfpu=vfpv3-d16)
2 changes: 1 addition & 1 deletion build/configs/toolchain_mcu_stm32f3.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
include(CMakeForceCompiler)

set(CMAKE_SYSTEM_NAME MCU)
set(CMAKE_SYSTEM_PROCESSOR armv7l)
set(CMAKE_SYSTEM_PROCESSOR armv7l-hf)
set(CMAKE_SYSTEM_VERSION STM32F3)

set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb -mcpu=cortex-m4 -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard)
Expand Down
2 changes: 1 addition & 1 deletion build/configs/toolchain_mcu_stm32f4.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
include(CMakeForceCompiler)

set(CMAKE_SYSTEM_NAME MCU)
set(CMAKE_SYSTEM_PROCESSOR armv7l)
set(CMAKE_SYSTEM_PROCESSOR armv7l-hf)
set(CMAKE_SYSTEM_VERSION STM32F4)

set(FLAGS_COMMON_ARCH -mlittle-endian -mthumb -mcpu=cortex-m4 -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard)
Expand Down
37 changes: 18 additions & 19 deletions jerry-core/ecma/builtin-objects/ecma-builtin-math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
#include "ecma-objects.h"
#include "ecma-objects-general.h"
#include "ecma-try-catch-macro.h"
#include "jrt.h"
#include "fdlibm-math.h"
#include "jrt.h"
#include "jrt-libc-includes.h"

#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN

Expand Down Expand Up @@ -528,26 +529,24 @@ ecma_builtin_math_object_pow (ecma_value_t this_arg __attr_unused___, /**< 'this
static ecma_completion_value_t
ecma_builtin_math_object_random (ecma_value_t this_arg __attr_unused___) /**< 'this' argument */
{
/* Implementation of George Marsaglia's XorShift random number generator */
TODO (/* Check for license issues */);

static uint32_t word1 = 1455997910;
static uint32_t word2 = 1999515274;
static uint32_t word3 = 1234451287;
static uint32_t word4 = 1949149569;

uint32_t intermediate = word1 ^ (word1 << 11);
intermediate ^= intermediate >> 8;

word1 = word2;
word2 = word3;
word3 = word4;

word4 ^= word4 >> 19;
word4 ^= intermediate;
uint32_t rnd = 1;
uint32_t reps_count;
#if RAND_MAX < 0x100
reps_count = 4;
#elif RAND_MAX < 0x10000
reps_count = 2;
#else /* RAND_MAX < 0x10000 */
reps_count = 1;
#endif /* RAND_MAX >= 0x10000 */

for (uint32_t i = 0; i < reps_count; i++)
{
uint32_t next_rand = (uint32_t) rand ();
rnd *= next_rand;
}

const uint32_t max_uint32 = (uint32_t) -1;
ecma_number_t rand = (ecma_number_t) word4;
ecma_number_t rand = (ecma_number_t) rnd;
rand /= (ecma_number_t) max_uint32;
rand *= (ecma_number_t) (max_uint32 - 1) / (ecma_number_t) max_uint32;

Expand Down
22 changes: 9 additions & 13 deletions jerry-libc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ set(COMPILE_FLAGS_LIBC "${COMPILE_FLAGS_JERRY} ${C_FLAGS_JERRY}")
# Architecture-specific
# x86_64
set(DEFINES_LIBC_X86_64 __TARGET_HOST_x64)
# ARMv7
set(DEFINES_LIBC_ARMV7 __TARGET_HOST_ARMv7)
# ARMv7-hf
set(DEFINES_LIBC_ARMV7_HF __TARGET_HOST_ARMv7 __TARGET_HOST_ARMv7_HARD_FLOAT)
# ARMv7-el
set(DEFINES_LIBC_ARMV7_EL __TARGET_HOST_ARMv7 __TARGET_HOST_ARMv7_SOFT_FLOAT)
# x86
set(DEFINES_LIBC_X86 __TARGET_HOST_x86)

Expand All @@ -50,15 +52,6 @@ set(COMPILE_FLAGS_LIBC "${COMPILE_FLAGS_JERRY} ${C_FLAGS_JERRY}")
set(INCLUDE_LIBC_INTERFACE ${CMAKE_SOURCE_DIR}/jerry-libc/include)
set(INCLUDE_LIBC_INTERFACE ${INCLUDE_LIBC_INTERFACE} PARENT_SCOPE)

# Platform-specific
# Linux
set(INCLUDE_LIBC_LINUX target/linux)
# MCU
# STM32F3
set(INCLUDE_LIBC_MCU_STM32F3 target/mcu-stubs)
# STM32F4
set(INCLUDE_LIBC_MCU_STM32F4 target/mcu-stubs)

# Third-party
# Platform-specific
# Linux
Expand Down Expand Up @@ -102,8 +95,10 @@ set(COMPILE_FLAGS_LIBC "${COMPILE_FLAGS_JERRY} ${C_FLAGS_JERRY}")
# Architecture-specific configuration
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
set(DEFINES_LIBC ${DEFINES_LIBC} ${DEFINES_LIBC_X86_64})
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
set(DEFINES_LIBC ${DEFINES_LIBC} ${DEFINES_LIBC_ARMV7})
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l-hf")
set(DEFINES_LIBC ${DEFINES_LIBC} ${DEFINES_LIBC_ARMV7_HF})
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l-el")
set(DEFINES_LIBC ${DEFINES_LIBC} ${DEFINES_LIBC_ARMV7_EL})
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86")
set(DEFINES_LIBC ${DEFINES_LIBC} ${DEFINES_LIBC_X86})
else()
Expand Down Expand Up @@ -148,3 +143,4 @@ set(COMPILE_FLAGS_LIBC "${COMPILE_FLAGS_JERRY} ${C_FLAGS_JERRY}")

declare_targets_for_build_mode(DEBUG)
declare_targets_for_build_mode(RELEASE)
declare_targets_for_build_mode(UNITTESTS)
179 changes: 179 additions & 0 deletions jerry-libc/arch/arm-v7.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/* 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_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};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Syscalls require to save all registers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't they? I would be grateful, if you would point to some accepted specification that describes system call-related requirements for saving register values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any documentation. But other libc implementations don't save them. The syscall implementation in the following link says: no registers are clobbered. I suspect the reason is avoid leaking information in registers for crackers.
https://chromium.googlesource.com/chromiumos/third_party/glibc-ports/+/factory-2460.B/sysdeps/unix/sysv/linux/arm/eabi/libc-do-syscall.S

I also checked the SWI implementation in the kernel. It starts with saving registers r0-r12
http://lxr.free-electrons.com/source/arch/arm/kernel/entry-common.S#L123

I seriously doubt that duplicating libc is a good idea. Systems with 1M ram does not run kernel, and we rely on their BSP. Systems with 16M ram has libc, and other applications (e.g. iot.js) will map it into the memory regardless of Jerry. So using libc is free from our perspective. Ultimately our duplicated libc just increase binary size. Maintenance is also difficult, and we cannot use optimizations (like register save skipping), because we want to be on the safe side. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and we cannot use optimizations (like register save skipping), because we want to be on the safe side.

In the case, we would oppose spending of several CPU cycles on each system call to possible reduce in code quality. As system call is relatively heavy operation, it seems to me that the optimization wouldn't somehow improve performance.

I seriously doubt that duplicating libc is a good idea. Systems with 1M ram does not run kernel, and we rely on their BSP. Systems with 16M ram has libc, and other applications (e.g. iot.js) will map it into the memory regardless of Jerry. So using libc is free from our perspective. Ultimately our duplicated libc just increase binary size. Maintenance is also difficult, and we cannot use optimizations (like register save skipping), because we want to be on the safe side. What do you think?

@zherczeg, thank you for sharing your view point. I think, it is better to continue the discussion in a 'discussion' issue, as it needs measurements and analysis for different platforms / configurations.


/*
* 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 */
Loading