Only generates asm code, and only support loadl, storel and addl for now.
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)
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])
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")
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])
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
#ifdef ENABLE_BACKEND_NEON
orc_neon_init();
#endif
+#ifdef ENABLE_BACKEND_MIPS
+ orc_mips_init();
+#endif
inited = TRUE;
}
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;
--- /dev/null
+#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));
+}
--- /dev/null
+#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_ */
--- /dev/null
+#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);
+}
+
--- /dev/null
+#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);
+}