#include "jit-internal.h"
#include "jit-rules.h"
#include "jit-apply-rules.h"
#if defined(JIT_BACKEND_ALPHA)
#include "jit-elf-defs.h"
#include "jit-gen-alpha.h"
#include "jit-reg-alloc.h"
#include "jit-setjmp.h"
#include <stdio.h>
int _alpha_has_ieeefp() {
unsigned long __implver;
__asm__ ("implver %0" : "=r"(__implver));
return (__implver >= 2);
}
#define ROUND_STACK(size) \
(((size) + (sizeof(alpha_inst) - 1)) & ~(sizeof(alpha_inst) - 1))
#define jit_cache_setup_output(needed) \
alpha_inst inst = (alpha_inst) gen->ptr; \
_jit_gen_check_space(gen, (needed))
#define jit_cache_end_output() \
gen->ptr = (unsigned char*) inst
#define jit_gen_load_inst_ptr(gen,inst) \
inst = (alpha_inst) (gen)->ptr;
#define jit_gen_save_inst_ptr(gen,inst) \
(gen)->ptr = (unsigned char *) inst;
static _jit_regclass_t *alpha_reg;
static _jit_regclass_t *alpha_freg;
void _jit_init_backend(void) {
alpha_reg = _jit_regclass_create("reg", JIT_REG_WORD | JIT_REG_LONG, 18,
ALPHA_T0, ALPHA_T1, ALPHA_T2, ALPHA_T3, ALPHA_T4, ALPHA_T5,
ALPHA_T6, ALPHA_T7, ALPHA_T8, ALPHA_T9, ALPHA_T10, ALPHA_T11,
ALPHA_S0, ALPHA_S1, ALPHA_S2, ALPHA_S3, ALPHA_S4, ALPHA_S5
);
alpha_freg = _jit_regclass_create("freg", JIT_REG_FLOAT32 | JIT_REG_FLOAT64 | JIT_REG_NFLOAT, 8,
ALPHA_FS0, ALPHA_FS1, ALPHA_FS2, ALPHA_FS3, ALPHA_FS4,
ALPHA_FS5, ALPHA_FS6, ALPHA_FS7, ALPHA_FT0, ALPHA_FT1,
ALPHA_FT2, ALPHA_FT3, ALPHA_FT4, ALPHA_FT5
);
}
#define TODO() \
do { \
fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \
} while (0)
void _jit_gen_get_elf_info(jit_elf_info_t *info) {
info->machine = EM_ALPHA;
info->abi = ELFOSABI_SYSV;
info->abi_version = 0;
}
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) {
unsigned int prolog[JIT_PROLOG_SIZE];
alpha_inst inst = prolog;
alpha_ldah(inst,ALPHA_GP,ALPHA_PV,0);
alpha_lda( inst,ALPHA_GP,ALPHA_GP,0);
alpha_lda(inst,ALPHA_SP,ALPHA_SP,-(2*8));
alpha_stq(inst,ALPHA_RA,ALPHA_SP,0*8);
alpha_stq(inst,ALPHA_FP,ALPHA_SP,1*8);
alpha_mov(inst,ALPHA_SP,ALPHA_FP);
alpha_trapb(inst);
jit_memcpy(buf, prolog, JIT_PROLOG_SIZE);
return (void *) buf;
}
void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) {
void **fixup, **next;
jit_cache_setup_output(20);
fixup = (void **)(gen->epilog_fixup);
while (fixup) {
alpha_inst code = (alpha_inst) fixup;
next = (void **)(fixup[0]);
_alpha_li64(code,ALPHA_AT,(long int)inst);
alpha_jmp(code,ALPHA_ZERO,ALPHA_AT,1);
fixup = next;
}
alpha_mov(inst,ALPHA_FP,ALPHA_SP);
alpha_ldq(inst,ALPHA_RA,ALPHA_SP,0*8);
alpha_ldq(inst,ALPHA_FP,ALPHA_SP,1*8);
alpha_lda(inst,ALPHA_SP,ALPHA_SP,16*8);
alpha_trapb(inst);
alpha_ret(inst,ALPHA_RA,1);
jit_cache_end_output();
}
int _jit_create_call_return_insns(jit_function_t func, jit_type_t signature, jit_value_t *args, unsigned int num_args, jit_value_t return_value, int is_nested) {
jit_type_t return_type;
int ptr_return;
return_type = jit_type_normalize(jit_type_get_return(signature));
ptr_return = jit_type_return_via_pointer(return_type);
if (!return_value || ptr_return) {
return 0;
}
if (jit_type_is_struct(return_type) || jit_type_is_union(return_type)) {
if (!jit_insn_flush_struct(func, return_value)) {
return 0;
}
} else if (return_type->kind == JIT_TYPE_FLOAT32 || return_type->kind == JIT_TYPE_FLOAT64 || return_type->kind == JIT_TYPE_NFLOAT) {
if (!jit_insn_return_reg(func, return_value, 32 )) {
return 0;
}
} else if (return_type->kind != JIT_TYPE_VOID) {
if (!jit_insn_return_reg(func, return_value, 0 )) {
return 0;
}
}
return 1;
}
int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value) {
TODO();
return 0;
}
void _jit_gen_exch_top(jit_gencode_t gen, int reg) {
;
}
void _jit_gen_move_top(jit_gencode_t gen, int reg) {
;
}
void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop) {
;
}
void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value) {
;
}
void _jit_gen_spill_reg(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) {
int offset;
jit_cache_setup_output(32);
if (value->has_global_register) {
alpha_mov(inst,_jit_reg_info[reg].cpu_reg,_jit_reg_info[value->global_reg].cpu_reg);
jit_cache_end_output();
return;
}
_jit_gen_fix_value(value);
offset = (int)(value->frame_offset);
if (reg < 32) {
alpha_stq(inst,reg,ALPHA_FP,offset);
if (other_reg != -1) {
offset += sizeof(void *);
alpha_stq(inst,other_reg,ALPHA_FP,offset);
}
} else {
}
jit_cache_end_output();
return;
}
void _jit_gen_free_reg(jit_gencode_t gen, int reg, int other_reg, int value_used) {
;
}
int _jit_opcode_is_supported(int opcode) {
switch(opcode) {
#define JIT_INCLUDE_SUPPORTED
#include "jit-rules-alpha.inc"
#undef JIT_INCLUDE_SUPPORTED
}
return 0;
}
int _jit_gen_is_global_candidate(jit_type_t type) {
switch(jit_type_remove_tags(type)->kind) {
case JIT_TYPE_INT:
case JIT_TYPE_UINT:
case JIT_TYPE_NINT:
case JIT_TYPE_NUINT:
case JIT_TYPE_PTR:
case JIT_TYPE_SIGNATURE:
return 1;
}
return 0;
}
void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block) {
void **fixup, **next;
block->address = (void *)(gen->ptr);
fixup = (void **)(block->fixup_list);
while (fixup) {
alpha_inst code = (alpha_inst) fixup;
next = (void **)(fixup[0]);
_alpha_li64(code,ALPHA_AT,(long int)(gen->ptr));
alpha_jmp(code,ALPHA_ZERO,ALPHA_AT,1);
fixup = next;
}
block->fixup_list = 0;
}
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block) {
;
}
void _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) {
short int offset;
jit_cache_setup_output(32);
if (value->is_constant) {
switch(jit_type_normalize(value->type)->kind) {
case JIT_TYPE_SBYTE:
case JIT_TYPE_UBYTE:
case JIT_TYPE_SHORT:
case JIT_TYPE_USHORT:
case JIT_TYPE_INT:
case JIT_TYPE_UINT:
case JIT_TYPE_LONG:
case JIT_TYPE_ULONG:
alpha_li(inst,_jit_reg_info[reg].cpu_reg,(jit_nint)(value->address));
break;
default:
break;
}
} else if (value->in_register || value->in_global_register) {
alpha_mov(inst,value->reg,_jit_reg_info[reg].cpu_reg);
} else {
_jit_gen_fix_value(value);
offset = (int)(value->frame_offset);
switch (jit_type_normalize(value->type)->kind) {
case JIT_TYPE_SBYTE:
break;
case JIT_TYPE_UBYTE:
alpha_ldbu(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
break;
case JIT_TYPE_SHORT:
break;
case JIT_TYPE_USHORT:
alpha_ldwu(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
break;
case JIT_TYPE_INT:
alpha_ldl(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
break;
case JIT_TYPE_UINT:
break;
case JIT_TYPE_LONG:
alpha_ldq(inst,_jit_reg_info[reg].cpu_reg,ALPHA_SP,offset);
break;
case JIT_TYPE_ULONG:
break;
case JIT_TYPE_FLOAT32:
case JIT_TYPE_FLOAT64:
case JIT_TYPE_NFLOAT:
break;
}
}
jit_cache_end_output();
}
void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) {
TODO();
}
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) {
void *ptr, *entry;
alpha_inst inst = (alpha_inst) gen->ptr;
_jit_gen_check_space(gen, 8*6);
ptr = (void *)&(func->entry_point);
entry = gen->ptr;
alpha_call(inst, ptr);
return entry;
}
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, jit_block_t block, jit_insn_t insn) {
switch (insn->opcode) {
#define JIT_INCLUDE_RULES
#include "jit-rules-alpha.inc"
#undef JIT_INCLUDE_RULES
default:
fprintf(stderr, "TODO(%x) at %s, %d\n", (int)(insn->opcode), __FILE__, (int)__LINE__);
break;
}
}
void _jit_gen_fix_value(jit_value_t value) {
if (!(value->has_frame_offset) && !(value->is_constant)) {
jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type)));
value->block->func->builder->frame_size += size;
value->frame_offset = -(value->block->func->builder->frame_size);
value->has_frame_offset = 1;
}
}
void alpha_output_branch(jit_function_t func, alpha_inst inst, int opcode, jit_insn_t insn, int reg) {
jit_block_t block;
if (!(block = jit_block_from_label(func, (jit_label_t)(insn->dest))))
return;
if (block->address) {
short offset = ((unsigned long) block->address - (unsigned long) inst);
alpha_encode_branch(inst,opcode,reg,offset);
} else {
long *addr = (void*) inst;
*addr = (long) block->fixup_list;
inst++; inst++;
_jit_pad_buffer((unsigned char*)inst,6);
}
}
void jump_to_epilog(jit_gencode_t gen, alpha_inst inst, jit_block_t block) {
long *addr = (void*) inst;
if(_jit_block_is_final(block))
{
return;
}
*addr = (long) gen->epilog_fixup;
inst++; inst++;
_jit_pad_buffer((unsigned char*)inst,6);
(gen)->ptr = (unsigned char*) inst;
}
#endif