#endif
}
-static void
+void
+powerpc_emit_load_address (OrcCompiler* compiler, int regd, int rega, int imm)
+{
+ if (compiler->is_64bit) {
+ powerpc_emit_ld (compiler, regd, rega, imm);
+ } else {
+ powerpc_emit_lwz (compiler, regd, rega, imm);
+ }
+}
+
+void
powerpc_load_constant (OrcCompiler *p, int i, int reg)
{
int j;
int value = p->constants[i].value;
+ int greg = p->gp_tmpreg;
switch (p->constants[i].type) {
case ORC_CONST_ZERO:
value &= 0xff;
value |= (value<<8);
value |= (value<<16);
+ value |= (value<<24);
for(j=0;j<4;j++){
p->constants[i].full_value[j] = value;
}
break;
}
- powerpc_load_long_constant (p, reg,
- p->constants[i].full_value[0],
- p->constants[i].full_value[1],
- p->constants[i].full_value[2],
- p->constants[i].full_value[3]);
-}
+ p->constants[i].is_long = TRUE;
+ if (p->constants[i].label == 0) {
+ p->constants[i].label = orc_compiler_label_new(p);
+ }
-void
-powerpc_load_long_constant (OrcCompiler *p, int reg, orc_uint32 a,
- orc_uint32 b, orc_uint32 c, orc_uint32 d)
-{
- int label_skip, label_data;
- int greg = p->gp_tmpreg;
+ powerpc_emit_load_address (p, greg, POWERPC_R3,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[ORC_VAR_A2]));
+ powerpc_emit_load_address (p, greg, greg,
+ (int)ORC_STRUCT_OFFSET(OrcCode, exec));
- label_skip = orc_compiler_label_new (p);
- label_data = orc_compiler_label_new (p);
+ powerpc_add_fixup (p, 1, p->codeptr, p->constants[i].label);
+ {
+ unsigned int insn;
- powerpc_emit_b (p, label_skip);
+ ORC_ASM_CODE(p," addi %s, %s, %db - %s\n",
+ powerpc_get_regname(greg),
+ powerpc_get_regname(greg), p->constants[i].label, p->program->name);
+ insn = (14<<26) | (powerpc_regnum (greg)<<21) | (powerpc_regnum (greg)<<16);
+ insn |= 0;
- while ((p->codeptr - p->code) & 0xf) {
- ORC_ASM_CODE(p," .long 0x00000000\n");
- powerpc_emit (p, 0x00000000);
+ powerpc_emit (p, insn);
}
- powerpc_emit_label (p, label_data);
+ ORC_ASM_CODE(p," lvx %s, 0, %s\n",
+ powerpc_get_regname(reg),
+ powerpc_get_regname(greg));
+ powerpc_emit_X (p, 0x7c0000ce, reg, 0, greg);
+}
+
+static void
+powerpc_emit_long_value(OrcCompiler* p, orc_uint32 a, orc_uint32 b,
+ orc_uint32 c, orc_uint32 d)
+{
if (IS_POWERPC_BE(p)) {
ORC_ASM_CODE(p," .long 0x%08x\n", a);
powerpc_emit (p, a);
ORC_ASM_CODE(p," .long 0x%08x\n", a);
powerpc_emit (p, a);
}
+}
- powerpc_emit_label (p, label_skip);
- if (p->is_64bit) {
- powerpc_emit_ld (p,
- greg,
- POWERPC_R3,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[ORC_VAR_A2]));
- powerpc_emit_ld (p,
- greg, greg,
- (int)ORC_STRUCT_OFFSET(OrcCode, exec));
- } else {
- powerpc_emit_lwz (p,
- greg,
- POWERPC_R3,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[ORC_VAR_A2]));
- powerpc_emit_lwz (p,
- greg, greg,
- (int)ORC_STRUCT_OFFSET(OrcCode, exec));
- }
-
- powerpc_add_fixup (p, 1, p->codeptr, label_data);
- {
- unsigned int insn;
-
- ORC_ASM_CODE(p," addi %s, %s, %db - %s\n",
- powerpc_get_regname(greg),
- powerpc_get_regname(greg), label_data, p->program->name);
- insn = (14<<26) | (powerpc_regnum (greg)<<21) | (powerpc_regnum (greg)<<16);
- insn |= 0;
-
- powerpc_emit (p, insn);
+void
+powerpc_emit_full_constants(OrcCompiler* p)
+{
+ int i;
+ int aligned = FALSE;
+
+ for (i = 0; i < p->n_constants; i++) {
+ if (p->constants[i].is_long == TRUE && p->constants[i].label) {
+ if (!aligned) {
+ while ((p->codeptr - p->code) & 0xf) {
+ ORC_ASM_CODE(p, " .long 0x00000000\n");
+ powerpc_emit(p, 0x00000000);
+ }
+ aligned = TRUE;
+ }
+ powerpc_emit_label(p, p->constants[i].label);
+ powerpc_emit_long_value(p,
+ p->constants[i].full_value[0], p->constants[i].full_value[1],
+ p->constants[i].full_value[2], p->constants[i].full_value[3]);
+ }
}
+}
- ORC_ASM_CODE(p," lvx %s, 0, %s\n",
- powerpc_get_regname(reg),
- powerpc_get_regname(greg));
- powerpc_emit_X (p, 0x7c0000ce, reg, 0, greg);
+void
+powerpc_load_long_constant (OrcCompiler *p, int reg, orc_uint32 value0,
+ orc_uint32 value1, orc_uint32 value2, orc_uint32 value3)
+{
+ int i = p->n_constants++;
+ p->constants[i].type = ORC_CONST_FULL;
+ p->constants[i].full_value[0] = value0;
+ p->constants[i].full_value[1] = value1;
+ p->constants[i].full_value[2] = value2;
+ p->constants[i].full_value[3] = value3;
+ p->constants[i].alloc_reg = -1;
+ powerpc_load_constant (p, i, reg);
}
int
for(i=0;i<p->n_constants;i++){
if (p->constants[i].type == type &&
p->constants[i].value == value) {
- if (p->constants[i].alloc_reg != 0) {
+ if (p->constants[i].alloc_reg > 0) {
return p->constants[i].alloc_reg;
}
break;
int i;
for(i=0;i<p->n_constants;i++){
-#if 0
- if (p->constants[i].type == type &&
- p->constants[i].value == value) {
- if (p->constants[i].alloc_reg != 0) {
+ if (p->constants[i].type == ORC_CONST_FULL &&
+ p->constants[i].full_value[0] == value0 &&
+ p->constants[i].full_value[1] == value1 &&
+ p->constants[i].full_value[2] == value2 &&
+ p->constants[i].full_value[3] == value3) {
+ if (p->constants[i].alloc_reg > 0) {
return p->constants[i].alloc_reg;
}
break;
}
-#endif
}
if (i == p->n_constants) {
p->n_constants++;
}
static void
+powerpc_load_constants_outer (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:
+ break;
+ case ORC_VAR_TYPE_PARAM:
+ break;
+ case ORC_VAR_TYPE_SRC:
+ case ORC_VAR_TYPE_DEST:
+ break;
+ case ORC_VAR_TYPE_ACCUMULATOR:
+ powerpc_emit_vxor(compiler, compiler->vars[i].alloc,
+ compiler->vars[i].alloc, compiler->vars[i].alloc);
+ break;
+ case ORC_VAR_TYPE_TEMP:
+ break;
+ default:
+ orc_compiler_error(compiler,"bad vartype");
+ break;
+ }
+ }
+
+ orc_compiler_emit_invariants (compiler);
+
+ for(i=0;i<compiler->n_constants;i++) {
+ if (compiler->constants[i].is_long &&
+ !compiler->constants[i].alloc_reg) {
+ compiler->constants[i].alloc_reg =
+ orc_compiler_get_constant_reg (compiler);
+ if (compiler->constants[i].alloc_reg > 0) {
+ powerpc_load_constant (compiler, i,
+ compiler->constants[i].alloc_reg);
+ }
+ }
+ }
+}
+
+static void
powerpc_load_inner_constants (OrcCompiler *compiler)
{
int i;
case ORC_VAR_TYPE_SRC:
case ORC_VAR_TYPE_DEST:
if (compiler->vars[i].ptr_register) {
- if (compiler->is_64bit) {
- powerpc_emit_ld (compiler,
- compiler->vars[i].ptr_register,
- POWERPC_R3,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
- } else {
- powerpc_emit_lwz (compiler,
- compiler->vars[i].ptr_register,
- POWERPC_R3,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
- }
+ powerpc_emit_load_address (compiler,
+ compiler->vars[i].ptr_register,
+ POWERPC_R3,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
} else {
/* FIXME */
ORC_ASM_CODE(compiler,"ERROR");
}
static void
-orc_compiler_powerpc_assemble (OrcCompiler *compiler)
+orc_powerpc_emit_loop (OrcCompiler* compiler, int update)
{
int j;
int k;
OrcInstruction *insn;
OrcStaticOpcode *opcode;
- /* OrcVariable *args[10]; */
OrcRule *rule;
+
+ for(j=0;j<compiler->n_insns;j++){
+ insn = compiler->insns + j;
+ opcode = insn->opcode;
+
+ compiler->insn_index = j;
+
+ if (insn->flags & ORC_INSN_FLAG_INVARIANT) continue;
+
+ ORC_ASM_CODE(compiler,"# %d: %s\n", j, insn->opcode->name);
+
+ compiler->min_temp_reg = ORC_VEC_REG_BASE;
+
+ compiler->insn_shift = compiler->loop_shift;
+ if (insn->flags & ORC_INSTRUCTION_FLAG_X2) {
+ compiler->insn_shift += 1;
+ }
+ if (insn->flags & ORC_INSTRUCTION_FLAG_X4) {
+ compiler->insn_shift += 2;
+ }
+
+ rule = insn->rule;
+ if (rule && rule->emit) {
+ rule->emit (compiler, rule->emit_user, insn);
+ } else {
+ orc_compiler_error (compiler, "no code generation rule for %s",
+ opcode->name);
+ }
+ }
+
+ if (update) {
+ for(k=0;k<ORC_N_COMPILER_VARIABLES;k++){
+ if (compiler->vars[k].name == NULL) continue;
+ if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
+ compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
+ if (compiler->vars[k].ptr_register) {
+ powerpc_emit_addi (compiler,
+ compiler->vars[k].ptr_register,
+ compiler->vars[k].ptr_register,
+ compiler->vars[k].size << compiler->loop_shift);
+ } else {
+ ORC_ASM_CODE(compiler,"ERROR\n");
+ }
+ }
+ }
+ }
+}
+
+static void
+orc_compiler_powerpc_assemble (OrcCompiler *compiler)
+{
+ int k;
int label_outer_loop_start;
int label_loop_start;
int label_leave;
label_loop_start = orc_compiler_label_new (compiler);
label_leave = orc_compiler_label_new (compiler);
+ {
+ int i;
+
+ orc_powerpc_emit_loop (compiler, 0);
+
+ compiler->codeptr = compiler->code;
+ free (compiler->asm_code);
+ compiler->asm_code = NULL;
+ compiler->asm_code_len = 0;
+ memset (compiler->labels, 0, sizeof (compiler->labels));
+ memset (compiler->labels_int, 0, sizeof (compiler->labels_int));
+ compiler->n_fixups = 0;
+ compiler->n_output_insns = 0;
+
+ for(i=0;i<compiler->n_constants;i++) {
+ compiler->constants[i].label = 0;
+ }
+ }
+
+ if (compiler->error) return;
+
powerpc_emit_prologue (compiler);
if (orc_program_has_float (compiler)) {
powerpc_emit_VX_b(compiler, "mtvscr", 0x10000644, tmp);
}
+ powerpc_load_constants_outer (compiler);
+
if (compiler->program->is_2d) {
powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m));
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index));
}
- /* powerpc_load_constants (compiler); */
powerpc_load_inner_constants (compiler);
- for(k=0;k<4;k++){
- OrcVariable *var = &compiler->vars[ORC_VAR_A1 + k];
-
- if (compiler->vars[ORC_VAR_A1 + k].name == NULL) continue;
-
- /* powerpc_emit_VX_2(p, "vxor", 0x100004c4, reg, reg, reg); */
- powerpc_emit_vxor (compiler, var->alloc, var->alloc, var->alloc);
- }
-
powerpc_emit_label (compiler, label_outer_loop_start);
powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3,
powerpc_emit_label (compiler, label_loop_start);
- for(j=0;j<compiler->n_insns;j++){
- insn = compiler->insns + j;
- opcode = insn->opcode;
-
- compiler->insn_index = j;
-
- ORC_ASM_CODE(compiler,"# %d: %s\n", j, insn->opcode->name);
-
-#if 0
- /* set up args */
- for(k=0;k<opcode->n_src + opcode->n_dest;k++){
- args[k] = compiler->vars + insn->args[k];
- ORC_ASM_CODE(compiler," %d", args[k]->alloc);
- if (args[k]->is_chained) {
- ORC_ASM_CODE(compiler," (chained)");
- }
- }
- ORC_ASM_CODE(compiler,"\n");
-#endif
-
- for(k=0;k<ORC_STATIC_OPCODE_N_SRC;k++){
- OrcVariable *var = compiler->vars + insn->src_args[k];
-
- if (opcode->src_size[k] == 0) continue;
-
- switch (var->vartype) {
- case ORC_VAR_TYPE_SRC:
- case ORC_VAR_TYPE_DEST:
- /* powerpc_emit_load_src (compiler, var); */
- break;
- case ORC_VAR_TYPE_CONST:
- break;
- case ORC_VAR_TYPE_TEMP:
- break;
- default:
- break;
- }
- }
-
- compiler->min_temp_reg = ORC_VEC_REG_BASE;
-
- rule = insn->rule;
- if (rule) {
- rule->emit (compiler, rule->emit_user, insn);
- } else {
- ORC_ASM_CODE(compiler,"No rule for: %s\n", opcode->name);
- }
-
- for(k=0;k<ORC_STATIC_OPCODE_N_DEST;k++){
- OrcVariable *var = compiler->vars + insn->dest_args[k];
-
- if (opcode->dest_size[k] == 0) continue;
-
- switch (var->vartype) {
- case ORC_VAR_TYPE_DEST:
- /* powerpc_emit_store_dest (compiler, var); */
- break;
- case ORC_VAR_TYPE_TEMP:
- break;
- default:
- break;
- }
- }
- }
-
- for(k=0;k<ORC_N_COMPILER_VARIABLES;k++){
- if (compiler->vars[k].name == NULL) continue;
- if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
- compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
- if (compiler->vars[k].ptr_register) {
- powerpc_emit_addi (compiler,
- compiler->vars[k].ptr_register,
- compiler->vars[k].ptr_register,
- compiler->vars[k].size << compiler->loop_shift);
- } else {
- ORC_ASM_CODE(compiler,"ERROR\n");
- }
- }
- }
+ orc_powerpc_emit_loop (compiler, 1);
powerpc_emit_bne (compiler, label_loop_start);
if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
if (compiler->vars[k].ptr_register) {
- if (compiler->is_64bit) {
- powerpc_emit_ld (compiler,
- compiler->vars[k].ptr_register,
- POWERPC_R3,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]));
- } else {
- powerpc_emit_lwz (compiler,
- compiler->vars[k].ptr_register,
- POWERPC_R3,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]));
- }
+ powerpc_emit_load_address (compiler,
+ compiler->vars[k].ptr_register,
+ POWERPC_R3,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]));
powerpc_emit_lwz (compiler,
POWERPC_R0,
POWERPC_R3,
}
powerpc_emit_epilogue (compiler);
+ powerpc_emit_full_constants (compiler);
+
powerpc_do_fixups (compiler);
}