issue #169 MIR update
parent
6f7313594c
commit
71e5bd8d8c
@ -0,0 +1,15 @@
|
||||
# Run this on LLVM 10 source dir
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake3 -DCMAKE_INSTALL_PREFIX=$HOME/Software/llvm10 \
|
||||
-DLLVM_TARGETS_TO_BUILD="X86" \
|
||||
-DLLVM_BUILD_TOOLS=OFF \
|
||||
-DLLVM_INCLUDE_TOOLS=OFF \
|
||||
-DLLVM_BUILD_EXAMPLES=OFF \
|
||||
-DLLVM_INCLUDE_EXAMPLES=OFF \
|
||||
-DLLVM_BUILD_TESTS=OFF \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
..
|
||||
cmake3 --build . --config Release --target install
|
@ -0,0 +1,23 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
#include "../mirc.h"
|
||||
#include "mirc-s390x-linux.h"
|
||||
|
||||
static const char *standard_includes[] = {mirc, s390x_mirc};
|
||||
|
||||
static const char *standard_include_dirs[] = {"include/mirc/", "include/mirc/s390x/"};
|
||||
|
||||
#define MAX_ALIGNMENT 16
|
||||
|
||||
#define ADJUST_VAR_ALIGNMENT(c2m_ctx, align, type) \
|
||||
s390x_adjust_var_alignment (c2m_ctx, align, type)
|
||||
|
||||
static int s390x_adjust_var_alignment (c2m_ctx_t c2m_ctx, int align, struct type *type) {
|
||||
return align;
|
||||
}
|
||||
|
||||
static int invalid_alignment (mir_llong align) {
|
||||
return align != 0 && align != 1 && align != 2 && align != 4 && align != 8 && align != 16;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MIR_CHAR_BIT 8
|
||||
|
||||
typedef int8_t mir_schar;
|
||||
typedef int16_t mir_short;
|
||||
typedef int32_t mir_int;
|
||||
typedef int64_t mir_long;
|
||||
typedef int64_t mir_llong;
|
||||
|
||||
#define MIR_SCHAR_MIN INT8_MIN
|
||||
#define MIR_SCHAR_MAX INT8_MAX
|
||||
#define MIR_SHORT_MIN INT16_MIN
|
||||
#define MIR_SHORT_MAX INT16_MAX
|
||||
#define MIR_INT_MIN INT32_MIN
|
||||
#define MIR_INT_MAX INT32_MAX
|
||||
#define MIR_LONG_MIN INT64_MIN
|
||||
#define MIR_LONG_MAX INT64_MAX
|
||||
#define MIR_LLONG_MIN INT64_MIN
|
||||
#define MIR_LLONG_MAX INT64_MAX
|
||||
|
||||
typedef uint8_t mir_uchar;
|
||||
typedef uint16_t mir_ushort;
|
||||
typedef uint32_t mir_uint;
|
||||
typedef uint64_t mir_ulong;
|
||||
typedef uint64_t mir_ullong;
|
||||
|
||||
#define MIR_UCHAR_MAX UINT8_MAX
|
||||
#define MIR_USHORT_MAX UINT16_MAX
|
||||
#define MIR_UINT_MAX UINT32_MAX
|
||||
#define MIR_ULONG_MAX UINT64_MAX
|
||||
#define MIR_ULLONG_MAX UINT64_MAX
|
||||
|
||||
typedef mir_schar mir_char;
|
||||
#define MIR_CHAR_MIN MIR_SCHAR_MIN
|
||||
#define MIR_CHAR_MAX MIR_SCHAR_MAX
|
||||
|
||||
typedef float mir_float;
|
||||
typedef double mir_double;
|
||||
typedef long double mir_ldouble;
|
||||
|
||||
typedef uint8_t mir_bool;
|
||||
typedef int64_t mir_ptrdiff_t;
|
||||
typedef uint64_t mir_size_t;
|
||||
|
||||
#define MIR_SIZE_MAX UINT64_MAX
|
@ -0,0 +1,102 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
static char s390x_mirc[]
|
||||
= "#define __zarch__ 1\n"
|
||||
"#define _LP64 1\n"
|
||||
"#define __LP64__ 1\n"
|
||||
"#define __s390__ 1\n"
|
||||
"#define __s390x__ 1\n"
|
||||
"#define __ELF__ 1\n"
|
||||
"\n"
|
||||
#if __SIZEOF_LONG_DOUBLE__ == 16
|
||||
"#define __LONG_DOUBLE_128__ 1\n" // ???
|
||||
"#define __SIZEOF_LONG_DOUBLE__ 16\n"
|
||||
#else
|
||||
"#define __SIZEOF_LONG_DOUBLE__ 8\n"
|
||||
#endif
|
||||
"#define __SIZEOF_FLOAT__ 4\n"
|
||||
"#define __SIZEOF_INT__ 4\n"
|
||||
"#define __SIZEOF_LONG_DOUBLE__ 16\n"
|
||||
"#define __SIZEOF_LONG_LONG__ 8\n"
|
||||
"#define __SIZEOF_LONG__ 8\n"
|
||||
"#define __SIZEOF_POINTER__ 8\n"
|
||||
"#define __SIZEOF_PTRDIFF_T__ 8\n"
|
||||
"#define __SIZEOF_SHORT__ 2\n"
|
||||
"#define __SIZEOF_SIZE_T__ 8\n"
|
||||
"\n"
|
||||
"#define __ORDER_LITTLE_ENDIAN__ 1234\n"
|
||||
"#define __ORDER_BIG_ENDIAN__ 4321\n"
|
||||
"#define _BIG_ENDIAN 1\n"
|
||||
"#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__\n"
|
||||
"\n"
|
||||
"/* Some GCC predefined macros: */\n"
|
||||
"#define __SIZE_TYPE__ unsigned long\n"
|
||||
"#define __PTRDIFF_TYPE__ long\n"
|
||||
"#define __INTMAX_TYPE__ long\n"
|
||||
"#define __UINTMAX_TYPE__ unsigned long\n"
|
||||
"#define __INT8_TYPE__ signed char\n"
|
||||
"#define __INT16_TYPE__ short\n"
|
||||
"#define __INT32_TYPE__ int\n"
|
||||
"#define __INT64_TYPE__ long\n"
|
||||
"#define __UINT8_TYPE__ unsigned char\n"
|
||||
"#define __UINT16_TYPE__ unsigned short\n"
|
||||
"#define __UINT32_TYPE__ unsigned int\n"
|
||||
"#define __UINT64_TYPE__ unsigned long\n"
|
||||
"#define __INTPTR_TYPE__ long\n"
|
||||
"#define __UINTPTR_TYPE__ unsigned long\n"
|
||||
"\n"
|
||||
"#define __CHAR_BIT__ 8\n"
|
||||
"#define __INT8_MAX__ 127\n"
|
||||
"#define __INT16_MAX__ 32767\n"
|
||||
"#define __INT32_MAX__ 2147483647\n"
|
||||
"#define __INT64_MAX__ 9223372036854775807l\n"
|
||||
"#define __UINT8_MAX__ (__INT8_MAX__ * 2u + 1u)\n"
|
||||
"#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n"
|
||||
"#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n"
|
||||
"#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n"
|
||||
"#define __SCHAR_MAX__ __INT8_MAX__\n"
|
||||
"#define __SHRT_MAX__ __INT16_MAX__\n"
|
||||
"#define __INT_MAX__ __INT32_MAX__\n"
|
||||
"#define __LONG_MAX__ __INT64_MAX__\n"
|
||||
"#define __LONG_LONG_MAX__ __INT64_MAX__\n"
|
||||
"#define __SIZE_MAX__ __UINT64_MAX__\n"
|
||||
"#define __PTRDIFF_MAX__ __INT64_MAX__\n"
|
||||
"#define __INTMAX_MAX__ __INT64_MAX__\n"
|
||||
"#define __UINTMAX_MAX__ __UINT64_MAX__\n"
|
||||
"#define __INTPTR_MAX__ __INT64_MAX__\n"
|
||||
"#define __UINTPTR_MAX__ __UINT64_MAX__\n"
|
||||
"\n"
|
||||
"#define __FLT_MIN_EXP__ (-125)\n"
|
||||
"#define __FLT_MAX_EXP__ 128\n"
|
||||
"#define __FLT_DIG__ 6\n"
|
||||
"#define __FLT_DECIMAL_DIG__ 9\n"
|
||||
"#define __FLT_MANT_DIG__ 24\n"
|
||||
"#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F\n"
|
||||
"#define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F\n"
|
||||
"#define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F\n"
|
||||
"\n"
|
||||
"#define __DBL_MIN_EXP__ (-1021)\n"
|
||||
"#define __DBL_MAX_EXP__ 1024\n"
|
||||
"#define __DBL_DIG__ 15\n"
|
||||
"#define __DBL_DECIMAL_DIG__ 17\n"
|
||||
"#define __DBL_MANT_DIG__ 53\n"
|
||||
"#define __DBL_MAX__ ((double) 1.79769313486231570814527423731704357e+308L)\n"
|
||||
"#define __DBL_MIN__ ((double) 2.22507385850720138309023271733240406e-308L)\n"
|
||||
"#define __DBL_EPSILON__ ((double) 2.22044604925031308084726333618164062e-16L)\n"
|
||||
"\n"
|
||||
"typedef unsigned short char16_t;\n"
|
||||
"typedef unsigned int char32_t;\n"
|
||||
"\n"
|
||||
#if defined(__linux__)
|
||||
"#define __gnu_linux__ 1\n"
|
||||
"#define __linux 1\n"
|
||||
"#define __linux__ 1\n"
|
||||
"#define linux 1\n"
|
||||
"#define unix 1\n"
|
||||
"#define __unix 1\n"
|
||||
"#define __unix__ 1\n"
|
||||
#endif
|
||||
"\n"
|
||||
"void *alloca (unsigned long);\n";
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,392 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2018-2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* Long doubles (-mlong-double=128) are always passed by its address (for args and results) */
|
||||
|
||||
#if 0 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#error "s390x works only in BE mode"
|
||||
#endif
|
||||
|
||||
#define VA_LIST_IS_ARRAY_P 1 /* one element array of struct s390x_va_list */
|
||||
|
||||
#define S390X_STACK_HEADER_SIZE 160
|
||||
|
||||
static void push_insns (MIR_context_t ctx, const uint8_t *pat, size_t pat_len) {
|
||||
for (size_t i = 0; i < pat_len; i++) VARR_PUSH (uint8_t, machine_insns, pat[i]);
|
||||
}
|
||||
|
||||
static void s390x_gen_mov (MIR_context_t ctx, unsigned to, unsigned from) {
|
||||
uint32_t lgr = (0xb904 << 16) | (to << 4) | from; /* lgr to,from: */
|
||||
assert (to < 16 && from < 16);
|
||||
push_insns (ctx, (uint8_t *) &lgr, 4);
|
||||
}
|
||||
|
||||
static void s390x_gen_mvi (MIR_context_t ctx, int val, unsigned base, int disp) {
|
||||
uint64_t mvghi /* mvghi disp(base), val: */
|
||||
= ((0xe548l << 32) | ((uint64_t) base << 28) | ((disp & 0xfff) << 16) | (val & 0xffff)) << 16;
|
||||
assert (base < 16 && 0 <= disp && disp < (1 << 12) && -(1 << 15) < val && val < (1 << 15));
|
||||
push_insns (ctx, (uint8_t *) &mvghi, 6);
|
||||
}
|
||||
|
||||
static void s390x_gen_ld_st (MIR_context_t ctx, unsigned reg, unsigned base, int disp,
|
||||
MIR_type_t type, int ld_p) {
|
||||
int single_p = type == MIR_T_F;
|
||||
int double_p = type == MIR_T_D;
|
||||
uint64_t dl = disp & 0xfff, dh = (disp >> 12) & 0xff;
|
||||
uint64_t common = ((uint64_t) reg << 36) | ((uint64_t) base << 28) | (dl << 16) | (dh << 8);
|
||||
uint64_t lgopcode
|
||||
= (type == MIR_T_I8
|
||||
? (ld_p ? 0x77 : 0x72)
|
||||
: type == MIR_T_U8 ? (ld_p ? 0x90 : 0x72)
|
||||
: type == MIR_T_I16
|
||||
? (ld_p ? 0x78 : 0x70)
|
||||
: type == MIR_T_U16
|
||||
? (ld_p ? 0x91 : 0x70)
|
||||
: type == MIR_T_I32 ? (ld_p ? 0x14 : 0x50)
|
||||
: type == MIR_T_U32 ? (ld_p ? 0x16 : 0x50)
|
||||
: (ld_p ? 0x04 : 0x24));
|
||||
uint64_t g = ((0xe3l << 40) | common | lgopcode) << 16;
|
||||
uint64_t ey = ((0xedl << 40) | common | (ld_p ? 0x64 : 0x66)) << 16;
|
||||
uint64_t dy = ((0xedl << 40) | common | (ld_p ? 0x65 : 0x67)) << 16;
|
||||
/* (lg|lgf|llgf|lgb|llgc|lhy|llgh|ley|ldy|stg|sty|sthy|stcy|stey|stdy) reg, disp(base): */
|
||||
assert (type != MIR_T_LD && reg < 16 && base < 16 && -(1 << 19) < disp && disp < (1 << 19));
|
||||
push_insns (ctx, (uint8_t *) (single_p ? &ey : double_p ? &dy : &g), 6);
|
||||
}
|
||||
|
||||
static void s390x_gen_ld (MIR_context_t ctx, unsigned to, unsigned base, int disp,
|
||||
MIR_type_t type) {
|
||||
s390x_gen_ld_st (ctx, to, base, disp, type, TRUE);
|
||||
}
|
||||
|
||||
static void s390x_gen_st (MIR_context_t ctx, unsigned from, unsigned base, int disp,
|
||||
MIR_type_t type) {
|
||||
s390x_gen_ld_st (ctx, from, base, disp, type, FALSE);
|
||||
}
|
||||
|
||||
static void s390x_gen_ldstm (MIR_context_t ctx, unsigned from, unsigned to, unsigned base, int disp,
|
||||
int ld_p) {
|
||||
uint64_t dl = disp & 0xfff, dh = (disp >> 12) & 0xff;
|
||||
uint64_t common = ((uint64_t) from << 36) | ((uint64_t) to << 32) | ((uint64_t) base << 28)
|
||||
| (dl << 16) | (dh << 8);
|
||||
uint64_t g = ((0xebl << 40) | common | (ld_p ? 0x4 : 0x24)) << 16;
|
||||
/* (lmg|stmg) from,to,disp(base): */
|
||||
assert (from < 16 && to < 16 && base < 16 && -(1 << 19) < disp && disp < (1 << 19));
|
||||
push_insns (ctx, (uint8_t *) &g, 6);
|
||||
}
|
||||
|
||||
static void s390x_gen_jump (MIR_context_t ctx, unsigned int reg, int call_p) {
|
||||
uint16_t bcr = (0x7 << 8) | (15 << 4) | reg; /* bcr 15,reg: */
|
||||
uint16_t balr = (0x5 << 8) | (14 << 4) | reg; /* balr 14,reg: */
|
||||
assert (reg < 16);
|
||||
push_insns (ctx, (uint8_t *) (call_p ? &balr : &bcr), 2);
|
||||
}
|
||||
|
||||
static void s390x_gen_addi (MIR_context_t ctx, unsigned dst, unsigned src, int disp) {
|
||||
uint64_t dl = disp & 0xfff, dh = (disp >> 12) & 0xff;
|
||||
uint64_t ops = ((uint64_t) dst << 36) | ((uint64_t) src << 28) | (dl << 16) | (dh << 8);
|
||||
uint64_t lay = ((0xe3l << 40) | ops | 0x71) << 16; /* lay dst,disp(src) */
|
||||
assert (dst < 16 && src < 16 && -(1 << 19) < disp && disp < (1 << 19));
|
||||
push_insns (ctx, (uint8_t *) &lay, 6);
|
||||
}
|
||||
|
||||
static void s390x_gen_3addrs (MIR_context_t ctx, unsigned int r1, void *a1, unsigned int r2,
|
||||
void *a2, unsigned int r3, void *a3) {
|
||||
/* 6b:lalr r3,22+align;6b:lg r1,0(r3);6b:lg r2,8(r3);6b:lg r3,16(r3);4b:bc m15,28;align;a1-a3 */
|
||||
size_t rem = (VARR_LENGTH (uint8_t, machine_insns) + 28) % 8;
|
||||
size_t padding = rem == 0 ? 0 : 8 - rem;
|
||||
uint64_t lalr = ((0xc0l << 40) | ((uint64_t) r1 << 36) | (28 + padding) / 2) << 16;
|
||||
uint32_t brc = (0xa7 << 24) | (15 << 20) | (4 << 16) | (28 + padding) / 2; /* brc m15,28: */
|
||||
assert (r1 != 0);
|
||||
push_insns (ctx, (uint8_t *) &lalr, 6);
|
||||
s390x_gen_ld (ctx, r3, r1, 16, MIR_T_I64); /* lg r3,16(r1) */
|
||||
s390x_gen_ld (ctx, r2, r1, 8, MIR_T_I64); /* lg r2,8(r1) */
|
||||
s390x_gen_ld (ctx, r1, r1, 0, MIR_T_I64); /* lg r1,0(r1) */
|
||||
push_insns (ctx, (uint8_t *) &brc, 4);
|
||||
for (size_t i = 0; i < padding; i++) VARR_PUSH (uint8_t, machine_insns, 0);
|
||||
push_insns (ctx, (uint8_t *) &a1, 8);
|
||||
push_insns (ctx, (uint8_t *) &a2, 8);
|
||||
push_insns (ctx, (uint8_t *) &a3, 8);
|
||||
}
|
||||
|
||||
void *_MIR_get_bstart_builtin (MIR_context_t ctx) {
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
s390x_gen_mov (ctx, 2, 15); /* lgr r2,15 */
|
||||
s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */
|
||||
return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
||||
|
||||
void *_MIR_get_bend_builtin (MIR_context_t ctx) {
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
s390x_gen_ld (ctx, 0, 15, 0, MIR_T_I64); /* r0 = 0(r15) */
|
||||
s390x_gen_st (ctx, 0, 2, 0, MIR_T_I64); /* 0(r2) = r0 */
|
||||
s390x_gen_mov (ctx, 15, 2); /* lgr r15,2 */
|
||||
s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */
|
||||
return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
||||
|
||||
void *_MIR_get_thunk (MIR_context_t ctx) {
|
||||
const int max_thunk_len = (4 * 8); /* see _MIR_redirect_thunk */
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
for (int i = 0; i < max_thunk_len; i++) VARR_PUSH (uint8_t, machine_insns, 0);
|
||||
return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
||||
|
||||
void _MIR_redirect_thunk (MIR_context_t ctx, void *thunk, void *to) {
|
||||
int64_t offset = (uint8_t *) to - (uint8_t *) thunk;
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
assert (offset % 2 == 0);
|
||||
offset /= 2;
|
||||
if (-(1l << 31) < offset && offset < (1l << 31)) { /* brcl m15,offset: */
|
||||
uint64_t brcl = ((0xc0l << 40) | (15l << 36) | (4l << 32) | offset & 0xffffffff) << 16;
|
||||
push_insns (ctx, (uint8_t *) &brcl, 6);
|
||||
} else { /* 6b:lalr r1,8+padding; 6b:lg r1,0(r1); 2b:bcr m15,r1;padding; 64-bit address: */
|
||||
size_t rem = (VARR_LENGTH (uint8_t, machine_insns) + 14) % 8;
|
||||
size_t padding = rem == 0 ? 0 : 8 - rem;
|
||||
uint64_t lalr = ((0xc0l << 40) | (1l << 36) | (14 + padding) / 2) << 16;
|
||||
uint64_t lg = ((0xe3l << 40) | (1l << 36) | (1l << 28) | 0x4) << 16;
|
||||
uint16_t bcr = (0x7 << 8) | (15 << 4) | 1; /* bcr 15,r1: */
|
||||
push_insns (ctx, (uint8_t *) &lalr, 6);
|
||||
push_insns (ctx, (uint8_t *) &lg, 6);
|
||||
push_insns (ctx, (uint8_t *) &bcr, 2);
|
||||
for (size_t i = 0; i < padding; i++) VARR_PUSH (uint8_t, machine_insns, 0);
|
||||
push_insns (ctx, (uint8_t *) &to, 8);
|
||||
}
|
||||
_MIR_change_code (ctx, thunk, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
||||
|
||||
struct s390x_va_list {
|
||||
long __gpr, __fpr; /* number of args read until now */
|
||||
void *__overflow_arg_area; /* argument on the stack to read next */
|
||||
void *__reg_save_area; /* curr func frame start */
|
||||
};
|
||||
|
||||
void *va_arg_builtin (void *p, uint64_t t) {
|
||||
struct s390x_va_list *va = p;
|
||||
MIR_type_t type = t;
|
||||
int fp_p = type == MIR_T_F || type == MIR_T_D;
|
||||
void *a;
|
||||
|
||||
if (!fp_p) {
|
||||
if (va->__gpr < 5) {
|
||||
a = (char *) va->__reg_save_area + 16 + 8 * va->__gpr;
|
||||
} else {
|
||||
a = va->__overflow_arg_area;
|
||||
va->__overflow_arg_area = (char *) va->__overflow_arg_area + 8;
|
||||
}
|
||||
va->__gpr++;
|
||||
if (type == MIR_T_LD) a = *(void **) a; /* always passed by address */
|
||||
} else {
|
||||
if (va->__fpr < 4) {
|
||||
a = (char *) va->__reg_save_area + 128 + 8 * va->__fpr;
|
||||
} else {
|
||||
a = va->__overflow_arg_area;
|
||||
va->__overflow_arg_area = (char *) va->__overflow_arg_area + 8;
|
||||
}
|
||||
va->__fpr++;
|
||||
}
|
||||
if (type == MIR_T_F || type == MIR_T_I32) a = (char *) a + 4; /* 2nd word of doubleword */
|
||||
return a;
|
||||
}
|
||||
|
||||
void va_start_interp_builtin (MIR_context_t ctx, void *p, void *a) {
|
||||
struct s390x_va_list *va = p;
|
||||
va_list *vap = a;
|
||||
|
||||
assert (sizeof (struct s390x_va_list) == sizeof (va_list));
|
||||
*va = *(struct s390x_va_list *) vap;
|
||||
}
|
||||
|
||||
void va_end_interp_builtin (MIR_context_t ctx, void *p) {}
|
||||
|
||||
/* Generation: fun (fun_addr, res_arg_addresses):
|
||||
save r6, r7, r14 (r15 + 48,112);
|
||||
allocate and stack frame (S390X_STACK_HEADER_SIZE + param area size + ld arg values size);
|
||||
r1=r2 (fun_addr);
|
||||
r7=r3 (res_arg_addresses);
|
||||
(arg_reg=mem[r7,arg_offset] or (f1,r0)=mem[r7,arg_offset];mem[r15,S390X_STACK_HEADER_SIZE+offset]=(f1,r0)) ...
|
||||
call *r1;
|
||||
r0=mem[r7,<res_offset>]; res_reg=mem[r0]; ...
|
||||
restore r15; restore r6, r7, r14; return. */
|
||||
void *_MIR_get_ff_call (MIR_context_t ctx, size_t nres, MIR_type_t *res_types, size_t nargs,
|
||||
MIR_type_t *arg_types, int vararg_p) {
|
||||
MIR_type_t type;
|
||||
int n_gpregs = 0, n_fpregs = 0, res_reg = 7, frame_size, disp, param_offset, param_size = 0;
|
||||
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
frame_size = S390X_STACK_HEADER_SIZE;
|
||||
if (nres > 0 && res_types[0] == MIR_T_LD) n_gpregs++; /* ld address */
|
||||
for (uint32_t i = 0; i < nargs; i++) { /* calculate param area size: */
|
||||
type = arg_types[i];
|
||||
if (type == MIR_T_LD) frame_size += 16; /* address for ld value */
|
||||
if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) {
|
||||
n_fpregs++;
|
||||
} else if (type != MIR_T_F && type != MIR_T_D && n_gpregs < 5) {
|
||||
n_gpregs++;
|
||||
} else {
|
||||
frame_size += 8;
|
||||
param_size += 8;
|
||||
}
|
||||
}
|
||||
s390x_gen_ldstm (ctx, 6, 7, 15, 48, FALSE); /* stmg 6,7,48(r15) : */
|
||||
s390x_gen_st (ctx, 14, 15, 112, MIR_T_I64); /* stg r14,112(r15) */
|
||||
s390x_gen_addi (ctx, 15, 15, -frame_size); /* lay r15,-frame_size(r15) */
|
||||
s390x_gen_mov (ctx, 1, 2); /* fun_addr */
|
||||
s390x_gen_mov (ctx, res_reg, 3); /* results & args */
|
||||
n_gpregs = n_fpregs = 0;
|
||||
param_offset = nres * 16; /* args start */
|
||||
disp = S390X_STACK_HEADER_SIZE; /* param area start */
|
||||
if (nres > 0 && res_types[0] == MIR_T_LD) { /* ld address: */
|
||||
s390x_gen_mov (ctx, 2, res_reg); /* lgr r2,r7 */
|
||||
n_gpregs++;
|
||||
}
|
||||
for (uint32_t i = 0; i < nargs; i++) { /* load args: */
|
||||
type = arg_types[i];
|
||||
if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) {
|
||||
/* (le,ld) (f0,f2,f4,f6),param_ofset(r7) */
|
||||
s390x_gen_ld (ctx, n_fpregs * 2, res_reg, param_offset, type);
|
||||
n_fpregs++;
|
||||
} else if (type == MIR_T_F || type == MIR_T_D) {
|
||||
s390x_gen_ld (ctx, 1, res_reg, param_offset, type); /* (le,ld) f1,param_offset(r7) */
|
||||
s390x_gen_st (ctx, 1, 15, disp, type); /* (ste,std) f1,disp(r15) */
|
||||
disp += 8;
|
||||
} else if (type == MIR_T_LD && n_gpregs < 5) { /* ld address */
|
||||
s390x_gen_addi (ctx, n_gpregs + 2, res_reg, param_offset); /* lay rn,param_offset(r7) */
|
||||
n_gpregs++;
|
||||
} else if (type == MIR_T_LD) { /* pass address of location in the result: */
|
||||
s390x_gen_addi (ctx, 0, res_reg, param_offset); /* lay r0,param_offset(r7) */
|
||||
s390x_gen_st (ctx, 0, 15, disp, MIR_T_I64); /* stg r0,disp(r15) */
|
||||
disp += 8;
|
||||
} else if (n_gpregs < 5) {
|
||||
s390x_gen_ld (ctx, n_gpregs + 2, res_reg, param_offset, MIR_T_I64); /* lg* rn,param_offset(r7) */
|
||||
n_gpregs++;
|
||||
} else {
|
||||
s390x_gen_ld (ctx, 0, res_reg, param_offset, MIR_T_I64); /* lg* r0,param_offset(r7) */
|
||||
s390x_gen_st (ctx, 0, 15, disp, MIR_T_I64); /* stg* r0,disp(r15) */
|
||||
disp += 8;
|
||||
}
|
||||
param_offset += 16;
|
||||
}
|
||||
s390x_gen_jump (ctx, 1, TRUE); /* call *r1 */
|
||||
n_gpregs = n_fpregs = 0;
|
||||
disp = 0;
|
||||
for (uint32_t i = 0; i < nres; i++) {
|
||||
type = res_types[i];
|
||||
if (type == MIR_T_LD) continue; /* do nothing: the result value is already in results */
|
||||
if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) {
|
||||
s390x_gen_st (ctx, n_fpregs * 2, res_reg, disp, type);
|
||||
n_fpregs++;
|
||||
} else if (type != MIR_T_F && type != MIR_T_D && n_gpregs < 1) { // just one gp reg
|
||||
s390x_gen_st (ctx, n_gpregs + 2, res_reg, disp, MIR_T_I64);
|
||||
n_gpregs++;
|
||||
} else {
|
||||
(*error_func) (MIR_ret_error, "s390x can not handle this combination of return values");
|
||||
}
|
||||
disp += 16;
|
||||
}
|
||||
s390x_gen_addi (ctx, 15, 15, frame_size); /* lay 15,frame_size(15) */
|
||||
s390x_gen_ldstm (ctx, 6, 7, 15, 48, TRUE); /* lmg 6,7,48(r15) : */
|
||||
s390x_gen_ld (ctx, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */
|
||||
s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */
|
||||
return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
||||
|
||||
/* Transform C call to call of void handler (MIR_context_t ctx, MIR_item_t func_item,
|
||||
va_list va, MIR_val_t *results):
|
||||
Brief: save all C call args to register save area; save r7, r14;
|
||||
allocate shim stack frame (S390X_STACK_HEADER_SIZE + space for results and va);
|
||||
call handler with args; move results to return regs; restore r7,r14,r15; return */
|
||||
void *_MIR_get_interp_shim (MIR_context_t ctx, MIR_item_t func_item, void *handler) {
|
||||
MIR_func_t func = func_item->u.func;
|
||||
uint32_t nres = func->nres, nargs = func->nargs;
|
||||
MIR_type_t type, *res_types = func->res_types;
|
||||
int disp, frame_size, local_var_size, n_gpregs, n_fpregs, va_list_disp, results_disp;
|
||||
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
frame_size = S390X_STACK_HEADER_SIZE; /* register save area */
|
||||
s390x_gen_st (ctx, 14, 15, 112, MIR_T_I64); /* stg 14,112(r15) */
|
||||
s390x_gen_ldstm (ctx, 2, 6, 15, 16, FALSE); /* stmg 2,6,16(r15) : */
|
||||
for (unsigned reg = 0; reg <= 6; reg += 2) /* stdy f0,f2,f4,f6,128(r15) : */
|
||||
s390x_gen_st (ctx, reg, 15, reg * 4 + 128, MIR_T_D);
|
||||
local_var_size = sizeof (struct s390x_va_list) + nres * 16; /* allocate va and results */
|
||||
va_list_disp = frame_size;
|
||||
results_disp = va_list_disp + sizeof (struct s390x_va_list);
|
||||
frame_size += local_var_size;
|
||||
assert (frame_size % 8 == 0);
|
||||
s390x_gen_addi (ctx, 15, 15, -frame_size);
|
||||
/* setup va: mvghi va(15),(0,1): __gpr */
|
||||
s390x_gen_mvi (ctx, nres > 0 && res_types[0] == MIR_T_LD ? 1 : 0, 15, va_list_disp);
|
||||
s390x_gen_mvi (ctx, 0, 15, va_list_disp + 8); /* mvghi va+8(15),0: __fpr */
|
||||
s390x_gen_addi (ctx, 1, 15, frame_size); /* lay 1,frame_size(15) */
|
||||
s390x_gen_st (ctx, 1, 15, va_list_disp + 24, MIR_T_I64); /* stg 1,va+24(r15): __reg_save_area */
|
||||
s390x_gen_addi (ctx, 1, 1, S390X_STACK_HEADER_SIZE); /* lay 1,S390X_STACK_HEADER_SIZE(1) */
|
||||
/* stg 1,va+16(r15):__overflow_arg_area: */
|
||||
s390x_gen_st (ctx, 1, 15, va_list_disp + 16, MIR_T_I64);
|
||||
/* call handler: */
|
||||
s390x_gen_3addrs (ctx, 2, ctx, 3, func_item, 1, handler);
|
||||
s390x_gen_addi (ctx, 4, 15, va_list_disp);
|
||||
s390x_gen_addi (ctx, 5, 15, results_disp);
|
||||
s390x_gen_jump (ctx, 1, TRUE);
|
||||
/* setup result regs: */
|
||||
disp = results_disp;
|
||||
n_gpregs = n_fpregs = 0;
|
||||
for (uint32_t i = 0; i < nres; i++) {
|
||||
type = res_types[i];
|
||||
if ((type == MIR_T_F || type == MIR_T_D) && n_fpregs < 4) {
|
||||
s390x_gen_ld (ctx, n_fpregs * 2, 15, disp, type);
|
||||
n_fpregs++;
|
||||
} else if (type != MIR_T_F && type != MIR_T_D && n_gpregs < 1) { // just one gp reg
|
||||
if (type != MIR_T_LD) {
|
||||
s390x_gen_ld (ctx, n_gpregs + 2, 15, disp, MIR_T_I64);
|
||||
} else {
|
||||
/* ld address: lg r2,16+frame_size(r15) */
|
||||
s390x_gen_ld (ctx, 2, 15, 16 + frame_size, MIR_T_I64);
|
||||
s390x_gen_ld (ctx, 0, 15, disp, MIR_T_D); /* ld f0,disp(r15) */
|
||||
s390x_gen_ld (ctx, 2, 15, disp + 8, MIR_T_D); /* ld f2,disp + 8(r15) */
|
||||
s390x_gen_st (ctx, 0, 2, 0, MIR_T_D); /* st f0,0(r2) */
|
||||
s390x_gen_st (ctx, 2, 2, 8, MIR_T_D); /* st f2,8(r2) */
|
||||
}
|
||||
n_gpregs++;
|
||||
} else {
|
||||
(*error_func) (MIR_ret_error, "s390x can not handle this combination of return values");
|
||||
}
|
||||
disp += 16;
|
||||
}
|
||||
s390x_gen_addi (ctx, 15, 15, frame_size); /* lay 15,frame_size(15) */
|
||||
s390x_gen_ld (ctx, 6, 15, 48, MIR_T_I64); /* lg 6,48(r15) : */
|
||||
s390x_gen_ld (ctx, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */
|
||||
s390x_gen_jump (ctx, 14, FALSE); /* bcr m15,r14 */
|
||||
return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
||||
|
||||
/* Brief: save r14 (r15+120); save all param regs r2-r6 (r15+16),f0,f2,f4,f6 (r15+128);
|
||||
update r15; allocate and form minimal wrapper stack frame (S390X_STACK_HEADER_SIZE);
|
||||
r2 = call hook_address (ctx, called_func); r1=r2; restore all params regs, r15, r14; bcr r1 */
|
||||
void *_MIR_get_wrapper (MIR_context_t ctx, MIR_item_t called_func, void *hook_address) {
|
||||
int frame_size = S390X_STACK_HEADER_SIZE;
|
||||
|
||||
VARR_TRUNC (uint8_t, machine_insns, 0);
|
||||
s390x_gen_st (ctx, 14, 15, 112, MIR_T_I64); /* stg 14,112(r15) */
|
||||
s390x_gen_ldstm (ctx, 2, 6, 15, 16, FALSE); /* stmg 2,6,16(r15) : */
|
||||
for (unsigned reg = 0; reg <= 6; reg += 2) /* stdy f0,f2,f4,f6,128(r15) : */
|
||||
s390x_gen_st (ctx, reg, 15, reg * 4 + 128, MIR_T_D);
|
||||
/* r15 -= frame_size: */
|
||||
s390x_gen_addi (ctx, 15, 15, -frame_size);
|
||||
s390x_gen_3addrs (ctx, 2, ctx, 3, called_func, 4, hook_address);
|
||||
s390x_gen_jump (ctx, 4, TRUE);
|
||||
s390x_gen_mov (ctx, 1, 2);
|
||||
s390x_gen_addi (ctx, 15, 15, frame_size);
|
||||
for (unsigned reg = 0; reg <= 6; reg += 2) /* ldy fn,disp(r15) : */
|
||||
s390x_gen_ld (ctx, reg, 15, reg * 4 + 128, MIR_T_D);
|
||||
s390x_gen_ldstm (ctx, 2, 6, 15, 16, TRUE); /* lmg 2,6,16(r15) : */
|
||||
s390x_gen_ld (ctx, 14, 15, 112, MIR_T_I64); /* lg 14,112(r15) */
|
||||
s390x_gen_jump (ctx, 1, FALSE);
|
||||
return _MIR_publish_code (ctx, VARR_ADDR (uint8_t, machine_insns),
|
||||
VARR_LENGTH (uint8_t, machine_insns));
|
||||
}
|
Loading…
Reference in new issue