Commit f6a8bd68 authored by Guillaume Emont's avatar Guillaume Emont

First version of mips target

Only generates asm code, and only support loadl, storel and addl for now.
parent b63cdec4
......@@ -119,7 +119,7 @@ AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_LIBS)
AC_ARG_ENABLE(backend,
AC_HELP_STRING([--enable-backend],[sse,mmx,neon,arm,all (default all)]),
AC_HELP_STRING([--enable-backend],[sse,mmx,neon,arm,mips,all (default all)]),
[], [enable_backend=all])
case "${enable_backend}" in
sse)
......@@ -146,6 +146,10 @@ case "${enable_backend}" in
ENABLE_BACKEND_C64X=yes
AC_DEFINE(ENABLE_BACKEND_C64X, 1, [Enable c64x backend])
;;
mips)
ENABLE_BACKEND_MIPS=yes
AC_DEFINE(ENABLE_BACKEND_MIPS, 1, [Enable MIPS backend])
;;
all|auto)
ENABLE_BACKEND_SSE=yes
AC_DEFINE(ENABLE_BACKEND_SSE, 1, [Enable SSE backend])
......@@ -159,6 +163,8 @@ case "${enable_backend}" in
AC_DEFINE(ENABLE_BACKEND_ARM, 1, [Enable Arm backend])
ENABLE_BACKEND_C64X=yes
AC_DEFINE(ENABLE_BACKEND_C64X, 1, [Enable c64x backend])
ENABLE_BACKEND_MIPS=yes
AC_DEFINE(ENABLE_BACKEND_MIPS, 1, [Enable MIPS backend])
;;
esac
AM_CONDITIONAL(ENABLE_BACKEND_SSE, test "x$ENABLE_BACKEND_SSE" = "xyes")
......@@ -167,6 +173,7 @@ AM_CONDITIONAL(ENABLE_BACKEND_ALTIVEC, test "x$ENABLE_BACKEND_ALTIVEC" = "xyes")
AM_CONDITIONAL(ENABLE_BACKEND_NEON, test "x$ENABLE_BACKEND_NEON" = "xyes")
AM_CONDITIONAL(ENABLE_BACKEND_ARM, test "x$ENABLE_BACKEND_ARM" = "xyes")
AM_CONDITIONAL(ENABLE_BACKEND_C64X, test "x$ENABLE_BACKEND_C64X" = "xyes")
AM_CONDITIONAL(ENABLE_BACKEND_MIPS, test "x$ENABLE_BACKEND_MIPS" = "xyes")
AC_DEFINE(ORC_EXPORTS, 1, [Defined for compiling internal code])
......
......@@ -58,6 +58,9 @@ endif
if ENABLE_BACKEND_C64X
liborc_@ORC_MAJORMINOR@_la_SOURCES += orcprogram-c64x-c.c
endif
if ENABLE_BACKEND_MIPS
liborc_@ORC_MAJORMINOR@_la_SOURCES += orcmips.c orcprogram-mips.c orcrules-mips.c
endif
if HAVE_I386
liborc_@ORC_MAJORMINOR@_la_SOURCES += orccpu-x86.c
......
......@@ -60,6 +60,9 @@ orc_init (void)
#ifdef ENABLE_BACKEND_NEON
orc_neon_init();
#endif
#ifdef ENABLE_BACKEND_MIPS
orc_mips_init();
#endif
inited = TRUE;
}
......
......@@ -17,6 +17,7 @@ void orc_c_init (void);
void orc_neon_init (void);
void orc_c64x_init (void);
void orc_c64x_c_init (void);
void orc_mips_init (void);
extern int _orc_data_cache_size_level1;
extern int _orc_data_cache_size_level2;
......
#include <orc/orcmips.h>
#include <orc/orcdebug.h>
const char *
orc_mips_reg_name (int reg)
{
static const char *regs[] = {
"$0", "$at",
"$v0", "$v1",
"$a0", "$a1", "$a2", "$a3",
"$t0", "$t1", "$t2", "$t3","$t4", "$t5", "$t6", "$t7",
"$s0", "$s1", "$s2", "$s3","$s4", "$s5", "$s6", "$s7",
"$t8", "$t9",
"$k0", "$k1",
"$gp", "$sp", "$fp", "$ra"
};
if (reg < ORC_GP_REG_BASE || reg > ORC_GP_REG_BASE + 32)
return "ERROR";
return regs[reg-32];
}
void
orc_mips_emit_label (OrcCompiler *compiler, unsigned int label)
{
ORC_ASSERT (label < ORC_N_LABELS);
ORC_ASM_CODE(compiler,".L%d:\n", label);
//compiler->labels[label] = compiler->codeptr;
}
void
orc_mips_emit_nop (OrcCompiler *compiler)
{
ORC_ASM_CODE(compiler," nop\n");
}
void
orc_mips_emit_sw (OrcCompiler *compiler, OrcMipsRegister reg,
OrcMipsRegister base, unsigned int offset)
{
ORC_ASM_CODE (compiler, " sw %s, %d(%s)\n",
orc_mips_reg_name (reg),
offset, orc_mips_reg_name (base));
}
void
orc_mips_emit_lw (OrcCompiler *compiler, OrcMipsRegister dest,
OrcMipsRegister base, unsigned int offset)
{
ORC_ASM_CODE (compiler, " lw %s, %d(%s)\n",
orc_mips_reg_name (dest),
offset, orc_mips_reg_name (base));
}
void
orc_mips_emit_jr (OrcCompiler *compiler, OrcMipsRegister address_reg)
{
ORC_ASM_CODE (compiler, " jr %s\n", orc_mips_reg_name (address_reg));
}
void
orc_mips_emit_blez (OrcCompiler *compiler,
OrcMipsRegister reg, unsigned int label)
{
ORC_ASM_CODE (compiler, " blez %s, .L%d\n",
orc_mips_reg_name (reg), label);
}
void
orc_mips_emit_bnez (OrcCompiler *compiler,
OrcMipsRegister reg, unsigned int label)
{
ORC_ASM_CODE (compiler, " bnez %s, .L%d\n",
orc_mips_reg_name (reg), label);
}
void
orc_mips_emit_addiu (OrcCompiler *compiler,
OrcMipsRegister dest, OrcMipsRegister source, int value)
{
ORC_ASM_CODE (compiler, " addiu %s, %s, %d\n",
orc_mips_reg_name (dest),
orc_mips_reg_name (source), value);
}
void
orc_mips_emit_add (OrcCompiler *compiler,
OrcMipsRegister dest,
OrcMipsRegister source1, OrcMipsRegister source2)
{
ORC_ASM_CODE (compiler, " add %s, %s, %s\n",
orc_mips_reg_name (dest),
orc_mips_reg_name (source1),
orc_mips_reg_name (source2));
}
#ifndef _ORC_MIPS_H_
#define _ORC_MIPS_H_
#include <orc/orcutils.h>
#include <orc/orcprogram.h>
ORC_BEGIN_DECLS
#ifdef ORC_ENABLE_UNSTABLE_API
typedef enum {
ORC_MIPS_ZERO = ORC_GP_REG_BASE+0,
ORC_MIPS_AT,
ORC_MIPS_V0,
ORC_MIPS_V1,
ORC_MIPS_A0,
ORC_MIPS_A1,
ORC_MIPS_A2,
ORC_MIPS_A3,
ORC_MIPS_T0,
ORC_MIPS_T1,
ORC_MIPS_T2,
ORC_MIPS_T3,
ORC_MIPS_T4,
ORC_MIPS_T5,
ORC_MIPS_T6,
ORC_MIPS_T7,
ORC_MIPS_S0,
ORC_MIPS_S1,
ORC_MIPS_S2,
ORC_MIPS_S3,
ORC_MIPS_S4,
ORC_MIPS_S5,
ORC_MIPS_S6,
ORC_MIPS_S7,
ORC_MIPS_T8,
ORC_MIPS_T9,
ORC_MIPS_K0,
ORC_MIPS_K1,
ORC_MIPS_GP,
ORC_MIPS_SP,
ORC_MIPS_FP,
ORC_MIPS_RA
} OrcMipsRegister;
void orc_mips_emit_label (OrcCompiler *compiler, unsigned int label);
void orc_mips_emit_nop (OrcCompiler *compiler);
void orc_mips_emit_sw (OrcCompiler *compiler, OrcMipsRegister reg,
OrcMipsRegister base, unsigned int offset);
void orc_mips_emit_lw (OrcCompiler *compiler, OrcMipsRegister dest,
OrcMipsRegister base, unsigned int offset);
void orc_mips_emit_jr (OrcCompiler *compiler, OrcMipsRegister address_reg);
void orc_mips_emit_blez (OrcCompiler *compiler, OrcMipsRegister reg, unsigned int label);
void orc_mips_emit_bnez (OrcCompiler *compiler, OrcMipsRegister reg, unsigned int label);
void orc_mips_emit_addiu (OrcCompiler *compiler, OrcMipsRegister dest, OrcMipsRegister source, int value);
void orc_mips_emit_add (OrcCompiler *compiler, OrcMipsRegister dest, OrcMipsRegister source1, OrcMipsRegister source2);
#endif /* ORC_ENABLE_UNSTABLE_API */
ORC_END_DECLS
#endif /* _ORC_MIPS_H_ */
#include <orc/orcmips.h>
#include <orc/orcdebug.h>
#include <stdlib.h>
unsigned int orc_compiler_orc_mips_get_default_flags (void);
void orc_compiler_orc_mips_init (OrcCompiler *compiler);
void orc_compiler_orc_mips_assemble (OrcCompiler *compiler);
const char * orc_compiler_orc_mips_get_asm_preamble (void);
/* in orcrules-mips.c */
void orc_compiler_orc_mips_register_rules (OrcTarget *target);
static OrcTarget orc_mips_target = {
"mips",
#ifdef HAVE_MIPS
TRUE,
#else
FALSE,
#endif
ORC_GP_REG_BASE,
orc_compiler_orc_mips_get_default_flags,
orc_compiler_orc_mips_init,
orc_compiler_orc_mips_assemble,
{ { 0 } },
0,
orc_compiler_orc_mips_get_asm_preamble,
};
void
orc_mips_init (void)
{
orc_target_register (&orc_mips_target);
orc_compiler_orc_mips_register_rules (&orc_mips_target);
}
unsigned int
orc_compiler_orc_mips_get_default_flags (void)
{
return 0;
}
void
orc_compiler_orc_mips_init (OrcCompiler *compiler)
{
int i;
for (i=ORC_GP_REG_BASE; i<ORC_GP_REG_BASE+32; i++)
compiler->valid_regs[i] = 1;
compiler->valid_regs[ORC_MIPS_ZERO] = 0; /* always 0 */
compiler->valid_regs[ORC_MIPS_AT] = 0; /* we shouldn't touch that (assembler
temporary) */
compiler->exec_reg = ORC_MIPS_A0;
compiler->valid_regs[ORC_MIPS_A0] = 0; /* first (and in our case only)
function argument */
compiler->valid_regs[ORC_MIPS_T0] = 0; /* We get the arg size here */
compiler->valid_regs[ORC_MIPS_K0] = 0; /* for kernel/interupts */
compiler->valid_regs[ORC_MIPS_K1] = 0; /* for kernel/interupts */
compiler->valid_regs[ORC_MIPS_GP] = 0; /* global pointer */
compiler->valid_regs[ORC_MIPS_SP] = 0; /* stack pointer */
compiler->valid_regs[ORC_MIPS_FP] = 0; /* frame pointer */
compiler->valid_regs[ORC_MIPS_RA] = 0; /* return address */
for (i=0;i<ORC_N_REGS;i++){
compiler->alloc_regs[i] = 0;
compiler->used_regs[i] = 0;
compiler->save_regs[i] = 0;
}
compiler->save_regs[ORC_MIPS_V0] = 1;
compiler->save_regs[ORC_MIPS_V1] = 1;
compiler->save_regs[ORC_MIPS_A1] = 1;
compiler->save_regs[ORC_MIPS_A2] = 1;
compiler->save_regs[ORC_MIPS_A3] = 1;
for (i=ORC_MIPS_S0; i<= ORC_MIPS_S7; i++)
compiler->save_regs[i] = 1;
/* what's compiler->gp_tmpreg? and ->tmpreg? */
}
const char *
orc_compiler_orc_mips_get_asm_preamble (void)
{
return "\n"
"/* begin Orc MIPS target preamble */\n"
".abicalls\n" /* not exactly sure what this is, but linker complains
without it */
"/* end Orc MIPS target preamble */\n\n";
}
int
orc_mips_emit_prologue (OrcCompiler *compiler)
{
int i, stack_size = 0;
orc_compiler_append_code(compiler,".globl %s\n", compiler->program->name);
orc_compiler_append_code(compiler,"%s:\n", compiler->program->name);
/* push registers we need to save */
for(i=0; i<32; i++)
if (compiler->used_regs[ORC_GP_REG_BASE + i] &&
compiler->save_regs[ORC_GP_REG_BASE + i])
stack_size += 4;
if (stack_size) {
unsigned int stack_increment = 0;
orc_mips_emit_addiu (compiler, ORC_MIPS_SP, ORC_MIPS_SP, -stack_size);
for(i=0; i<32; i++){
if (compiler->used_regs[ORC_GP_REG_BASE + i] &&
compiler->save_regs[ORC_GP_REG_BASE + i]) {
orc_mips_emit_sw (compiler, ORC_GP_REG_BASE+i,
ORC_MIPS_SP, stack_increment);
stack_increment +=4;
}
}
}
return stack_size;
}
void orc_mips_emit_epilogue (OrcCompiler *compiler, int stack_size)
{
int i;
/* pop saved registers */
if (stack_size) {
unsigned int stack_increment = 0;
for(i=0; i<32; i++){
if (compiler->used_regs[ORC_GP_REG_BASE + i] &&
compiler->save_regs[ORC_GP_REG_BASE + i]) {
orc_mips_emit_lw (compiler, ORC_GP_REG_BASE+i,
ORC_MIPS_SP, stack_increment);
stack_increment +=4;
}
}
orc_mips_emit_addiu (compiler, ORC_MIPS_SP, ORC_MIPS_SP, stack_size);
}
orc_mips_emit_jr (compiler, ORC_MIPS_RA);
orc_mips_emit_nop (compiler);
}
void
orc_mips_load_constants_inner (OrcCompiler *compiler)
{
int i;
for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){
if (compiler->vars[i].name == NULL) continue;
switch (compiler->vars[i].vartype) {
case ORC_VAR_TYPE_CONST:
case ORC_VAR_TYPE_PARAM:
break;
case ORC_VAR_TYPE_SRC:
case ORC_VAR_TYPE_DEST:
orc_mips_emit_lw (compiler,
compiler->vars[i].ptr_register,
compiler->exec_reg, ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
break;
default:
break;
}
}
}
void
orc_mips_emit_loop (OrcCompiler *compiler)
{
int i, j;
OrcInstruction *insn;
OrcStaticOpcode *opcode;
OrcRule *rule;
for (i=0; i<compiler->n_insns; i++) {
insn = compiler->insns + i;
opcode = insn->opcode;
if (insn->flags & ORC_INSN_FLAG_INVARIANT) continue;
orc_compiler_append_code(compiler,"/* %d: %s */\n", i, insn->opcode->name);
rule = insn->rule;
if (rule && rule->emit) {
rule->emit (compiler, rule->emit_user, insn);
} else {
orc_compiler_append_code (compiler, "No rule for %s\n", opcode->name);
}
}
for (j=0; j<ORC_N_COMPILER_VARIABLES; j++) {
if (compiler->vars[j].name == NULL) continue;
if (compiler->vars[j].vartype == ORC_VAR_TYPE_SRC ||
compiler->vars[j].vartype == ORC_VAR_TYPE_DEST) {
if (compiler->vars[j].ptr_register) {
orc_mips_emit_addiu (compiler,
compiler->vars[j].ptr_register,
compiler->vars[j].ptr_register,
compiler->vars[j].size << compiler->loop_shift);
}
}
}
}
void
orc_compiler_orc_mips_assemble (OrcCompiler *compiler)
{
int stack_size;
stack_size = orc_mips_emit_prologue (compiler);
/* FIXME: load constants and params */
#if 0
for (i=0; i<ORC_N_COMPILER_VARIABLES; i++) {
if (compiler->vars[i].name == NULL)
ORC_PROGRAM_ERROR (compiler, "unimplemented");
}
#endif
/* FIXME */
if (compiler->program->is_2d)
ORC_PROGRAM_ERROR (compiler, "unimplemented");
orc_mips_emit_lw (compiler, ORC_MIPS_T0, compiler->exec_reg,
(int)ORC_STRUCT_OFFSET(OrcExecutor, n));
orc_mips_emit_blez (compiler, ORC_MIPS_T0, 2);
orc_mips_emit_nop (compiler);
orc_mips_load_constants_inner (compiler);
orc_mips_emit_label (compiler, 1);
orc_mips_emit_loop (compiler);
orc_mips_emit_addiu (compiler, ORC_MIPS_T0, ORC_MIPS_T0, -1);
orc_mips_emit_bnez (compiler, ORC_MIPS_T0, 1);
orc_mips_emit_nop (compiler);
orc_mips_emit_label (compiler, 2);
orc_mips_emit_epilogue (compiler, stack_size);
}
#include <orc/orcmips.h>
#include <stdlib.h>
void
mips_rule_loadl (OrcCompiler *compiler, void *user, OrcInstruction *insn)
{
int src = compiler->vars[insn->src_args[0]].ptr_register;
int dest = compiler->vars[insn->dest_args[0]].alloc;
orc_mips_emit_lw (compiler, dest, src, 0);
}
void
mips_rule_storel (OrcCompiler *compiler, void *user, OrcInstruction *insn)
{
int src = compiler->vars[insn->src_args[0]].alloc;
int dest = compiler->vars[insn->dest_args[0]].ptr_register;
orc_mips_emit_sw (compiler, src, dest, 0);
}
void
mips_rule_addl (OrcCompiler *compiler, void *user, OrcInstruction *insn)
{
int src1 = ORC_SRC_ARG (compiler, insn, 0);
int src2 = ORC_SRC_ARG (compiler, insn, 1);
int dest = ORC_DEST_ARG (compiler, insn, 0);
orc_mips_emit_add (compiler, dest, src1, src2);
}
void
orc_compiler_orc_mips_register_rules (OrcTarget *target)
{
OrcRuleSet *rule_set;
rule_set = orc_rule_set_new (orc_opcode_set_get("sys"), target, 0);
orc_rule_register (rule_set, "loadl", mips_rule_loadl, NULL);
orc_rule_register (rule_set, "storel", mips_rule_storel, NULL);
orc_rule_register (rule_set, "addl", mips_rule_addl, NULL);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment