diff options
| author | kyeongwoon <kyeongwoon.lee@samsung.com> | 2012-11-30 09:21:49 +0900 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-01-13 16:43:39 -0800 |
| commit | 987f824f233faee4aed39dac92a1b442d42965cc (patch) | |
| tree | 2cf1b078738e9bf580b9ee43f674d95c403751fa /src/rt/arch | |
| parent | 27e6a0fa5651dbda55773488c8b706adfa5cefc2 (diff) | |
| download | rust-987f824f233faee4aed39dac92a1b442d42965cc.tar.gz rust-987f824f233faee4aed39dac92a1b442d42965cc.zip | |
Support ARM and Android
Conflicts: src/libcore/os.rs src/librustc/back/link.rs src/librustc/driver/driver.rs src/librustc/metadata/loader.rs src/librustc/middle/trans/base.rs
Diffstat (limited to 'src/rt/arch')
| -rw-r--r-- | src/rt/arch/arm/_context.S | 47 | ||||
| -rw-r--r-- | src/rt/arch/arm/ccall.S | 27 | ||||
| -rw-r--r-- | src/rt/arch/arm/context.cpp | 36 | ||||
| -rw-r--r-- | src/rt/arch/arm/context.h | 43 | ||||
| -rw-r--r-- | src/rt/arch/arm/gpr.cpp | 15 | ||||
| -rw-r--r-- | src/rt/arch/arm/gpr.h | 23 | ||||
| -rw-r--r-- | src/rt/arch/arm/record_sp.S | 61 | ||||
| -rw-r--r-- | src/rt/arch/arm/regs.h | 21 |
8 files changed, 273 insertions, 0 deletions
diff --git a/src/rt/arch/arm/_context.S b/src/rt/arch/arm/_context.S new file mode 100644 index 00000000000..8d370c2d64e --- /dev/null +++ b/src/rt/arch/arm/_context.S @@ -0,0 +1,47 @@ +.text +.code 32 +.arm +.align + + +.globl swap_registers +swap_registers: + str r0, [r0, #0] + str r3, [r0, #12] + str r4, [r0, #16] + str r5, [r0, #20] + str r6, [r0, #24] + str r7, [r0, #28] + str r8, [r0, #32] + str r9, [r0, #36] + str r10, [r0, #40] + str r11, [r0, #44] + str r12, [r0, #48] + str sp, [r0, #52] + str lr, [r0, #56] + + mrs r2, cpsr + str r2, [r0, #64] + + + ldr r0, [r1, #0] + ldr r3, [r1, #12] + ldr r4, [r1, #16] + ldr r5, [r1, #20] + ldr r6, [r1, #24] + ldr r7, [r1, #28] + ldr r8, [r1, #32] + ldr r9, [r1, #36] + ldr r10, [r1, #40] + ldr r11, [r1, #44] + ldr r12, [r1, #48] + + ldr sp, [r1, #52] + ldr lr, [r1, #56] + + ldr r2, [r1, #64] + msr cpsr_cxsf, r2 + + mov pc, lr + + diff --git a/src/rt/arch/arm/ccall.S b/src/rt/arch/arm/ccall.S new file mode 100644 index 00000000000..4b89cc994a7 --- /dev/null +++ b/src/rt/arch/arm/ccall.S @@ -0,0 +1,27 @@ +.text +.code 32 +.arm +.align + +.globl __morestack +.hidden __morestack +__morestack: + mov r3, sp + mov sp, r2 + + str r3, [sp] + str lr, [sp, #-4] + + sub sp, #8 + + blx r1 + + add sp, #8 + + ldr lr, [sp, #-4] + ldr r3, [sp] + + mov sp, r3 + mov pc, lr + + diff --git a/src/rt/arch/arm/context.cpp b/src/rt/arch/arm/context.cpp new file mode 100644 index 00000000000..dbf06a532a8 --- /dev/null +++ b/src/rt/arch/arm/context.cpp @@ -0,0 +1,36 @@ + +#include "context.h" +#include "../../rust_globals.h" + +extern "C" void CDECL swap_registers(registers_t *oregs, + registers_t *regs) +asm ("swap_registers"); + +context::context() +{ + assert((void*)®s == (void*)this); + memset(®s, 0, sizeof(regs)); +} + +void context::swap(context &out) +{ + swap_registers(&out.regs, ®s); +} + +void context::call(void *f, void *arg, void *stack) +{ + // Get the current context, which we will then modify to call the + // given function. + swap(*this); + + // set up the stack + uint32_t *sp = ( uint32_t *)stack; + //sp = align_down(sp); + // The final return address. 0 indicates the bottom of the stack + *--sp = 0; + + regs.data[0] = ( uint32_t )arg; // r0 + regs.data[13] = ( uint32_t )sp; //#52 sp, r13 + regs.data[14] = ( uint32_t )f; //#60 pc, r15 --> lr, + // Last base pointer on the stack should be 0 +} diff --git a/src/rt/arch/arm/context.h b/src/rt/arch/arm/context.h new file mode 100644 index 00000000000..6c7db766d6a --- /dev/null +++ b/src/rt/arch/arm/context.h @@ -0,0 +1,43 @@ +// -*- mode: c++ -*- + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include <cstdlib> +#include <inttypes.h> +#include <stdint.h> +//#include <xmmintrin.h> + +#include "vg/memcheck.h" + +template<typename T> +T align_down(T sp) +{ + // There is no platform we care about that needs more than a + // 16-byte alignment. + return (T)((uint32_t)sp & ~(16 - 1)); +} + +// The struct in which we store the saved data. This is mostly the +// volatile registers and instruction pointer, but it also includes +// RCX/RDI which are used to pass arguments. The indices for each +// register are found in "regs.h". Note that the alignment must be +// 16 bytes so that SSE instructions can be used. +#include "regs.h" +struct registers_t { + uint32_t data[RUSTRT_MAX]; +} __attribute__((aligned(16))); + +class context { +public: + registers_t regs; + + context(); + + context *next; + + void swap(context &out); + void call(void *f, void *arg, void *sp); +}; + +#endif diff --git a/src/rt/arch/arm/gpr.cpp b/src/rt/arch/arm/gpr.cpp new file mode 100644 index 00000000000..32a68d0732a --- /dev/null +++ b/src/rt/arch/arm/gpr.cpp @@ -0,0 +1,15 @@ +#include "gpr.h" + +#define LOAD(rn) do { \ + uintptr_t tmp; \ + asm("mov %%" #rn ",%0" : "=r" (tmp) :); \ + this->rn = tmp; \ +} while (0) + +void rust_gpr::load() { + LOAD(r0); LOAD(r1); LOAD(r2); LOAD(r3); + LOAD(r4); LOAD(r5); LOAD(r6); LOAD(r7); + LOAD(r8); LOAD(r9); LOAD(r10); LOAD(r11); + LOAD(r12); LOAD(r13); LOAD(r14); LOAD(r15); +} + diff --git a/src/rt/arch/arm/gpr.h b/src/rt/arch/arm/gpr.h new file mode 100644 index 00000000000..472c8a05e35 --- /dev/null +++ b/src/rt/arch/arm/gpr.h @@ -0,0 +1,23 @@ +// General-purpose registers. This structure is used during stack crawling. + +#ifndef GPR_H +#define GPR_H + +#include "rust_gpr_base.h" + +class rust_gpr : public rust_gpr_base { +public: + uintptr_t r0, r1, r2, r3, r4, r5, r6, r7; + uintptr_t r8, r9, r10, r11, r12, r13, r14, r15; + + inline uintptr_t get_fp() { return r11; } + inline uintptr_t get_ip() { return r12; } + + inline void set_fp(uintptr_t new_fp) { r11 = new_fp; } + inline void set_ip(uintptr_t new_ip) { r12 = new_ip; } + + void load(); +}; + +#endif + diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S new file mode 100644 index 00000000000..193104d53b1 --- /dev/null +++ b/src/rt/arch/arm/record_sp.S @@ -0,0 +1,61 @@ +.text +.code 32 +.arm +.align + + +.globl record_sp_limit +.globl get_sp_limit +.globl get_sp + +record_sp_limit: + mov r3, r0 + ldr r0, =my_cpu + mov r1, #0 + mov r2, #0 + stmfd sp!, {r3, r7} + ldr r7, =345 + swi #0 + ldmfd sp!, {r3, r7} + movs r0, r0 + movmi r0, #0 + + ldr r1, =my_array + str r3, [r1, r0] + mov pc, lr + + +get_sp_limit: + ldr r0, =my_cpu + mov r1, #0 + mov r2, #0 + stmfd sp!, {r4, r7} + ldr r7, =345 + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + movmi r0, #0 + mov r3, r0 + + ldr r1, =my_array + ldr r0, [r1, r3] + mov pc, lr + + +get_sp: + mov r0, sp + mov pc, lr + +.data +my_cpu: .long 0 +.global my_array +my_array: + .long 0 + .long 0 + .long 0 + .long 0 + .long 0 + .long 0 + .long 0 + .long 0 +.end diff --git a/src/rt/arch/arm/regs.h b/src/rt/arch/arm/regs.h new file mode 100644 index 00000000000..a49fcab1184 --- /dev/null +++ b/src/rt/arch/arm/regs.h @@ -0,0 +1,21 @@ +#define RUSTRT_RBX 0 +#define RUSTRT_RSP 1 +#define RUSTRT_RBP 2 +// RCX on Windows, RDI elsewhere +#define RUSTRT_ARG0 3 +#define RUSTRT_R12 4 +#define RUSTRT_R13 5 +#define RUSTRT_R14 6 +#define RUSTRT_R15 7 +#define RUSTRT_IP 8 + +#define RUSTRT_MAX 32 + +// ARG0 is the register in which the first argument goes. +// Naturally this depends on your operating system. +# define RUSTRT_ARG0_S r0 +# define RUSTRT_ARG1_S r1 +# define RUSTRT_ARG2_S r2 +# define RUSTRT_ARG3_S r3 + + |
