diff options
author | David Schleef <ds@ginger.bigkitten.com> | 2008-05-18 10:00:54 -0700 |
---|---|---|
committer | David Schleef <ds@ginger.bigkitten.com> | 2008-05-18 10:00:54 -0700 |
commit | f35e4adb51a0347ca28c766e9b62d4600882ab23 (patch) | |
tree | 366e5c07d4acdf6cfd261153b339cc6c4bf0d414 | |
parent | 54ec478a35384574bd593fc34a06bd7a2f88e4c5 (diff) | |
download | liboil-f35e4adb51a0347ca28c766e9b62d4600882ab23.tar.gz |
[orc] handle immediate operands
-rw-r--r-- | orc/orcprogram-x86.c | 71 | ||||
-rw-r--r-- | orc/orcprogram.c | 20 | ||||
-rw-r--r-- | orc/orcprogram.h | 1 |
3 files changed, 73 insertions, 19 deletions
diff --git a/orc/orcprogram-x86.c b/orc/orcprogram-x86.c index c669cca..6757d4c 100644 --- a/orc/orcprogram-x86.c +++ b/orc/orcprogram-x86.c @@ -210,7 +210,9 @@ orc_program_compile_x86 (OrcProgram *program) x86_emit_mov_memoffset_reg (program, 2, 0, X86_ECX, args[k]->alloc); break; case ORC_VAR_TYPE_CONST: - x86_emit_mov_imm_reg (program, 2, args[k]->s16, args[k]->alloc); + if (args[k]->alloc != 1) { + x86_emit_mov_imm_reg (program, 2, args[k]->s16, args[k]->alloc); + } break; case ORC_VAR_TYPE_TEMP: #if 0 @@ -283,15 +285,33 @@ orc_program_compile_x86 (OrcProgram *program) static void x86_rule_add_s16 (OrcProgram *p, void *user, OrcInstruction *insn) { - g_print(" addw %%%s, %%%s\n", - x86_get_regname_16(p->vars[insn->args[2]].alloc), - x86_get_regname_16(p->vars[insn->args[0]].alloc)); - - *p->codeptr++ = 0x66; - *p->codeptr++ = 0x03; - x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, - p->vars[insn->args[0]].alloc); + if (insn->rule_flag == ORC_RULE_REG_IMM) { + int value = p->vars[insn->args[2]].s16; + g_print(" addw $%d, %%%s\n", value, + x86_get_regname_16(p->vars[insn->args[0]].alloc)); + if (value >= -128 && value < 128) { + *p->codeptr++ = 0x66; + *p->codeptr++ = 0x83; + x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 0); + *p->codeptr++ = value; + } else { + *p->codeptr++ = 0x66; + *p->codeptr++ = 0x81; + x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 0); + *p->codeptr++ = value & 0xff; + *p->codeptr++ = value >> 8; + } + } else { + g_print(" addw %%%s, %%%s\n", + x86_get_regname_16(p->vars[insn->args[2]].alloc), + x86_get_regname_16(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x66; + *p->codeptr++ = 0x03; + x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, + p->vars[insn->args[0]].alloc); + } } static void @@ -337,14 +357,31 @@ x86_rule_lshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn) static void x86_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn) { - x86_emit_mov_reg_reg(p, 4, p->vars[insn->args[2]].alloc, X86_ECX); + if (insn->rule_flag == ORC_RULE_REG_IMM) { + g_print(" sarw $%d, %%%s\n", + p->vars[insn->args[2]].s16, + x86_get_regname_16(p->vars[insn->args[0]].alloc)); - g_print(" sarw %%cl, %%%s\n", - x86_get_regname_16(p->vars[insn->args[0]].alloc)); + if (p->vars[insn->args[2]].s16 == 1) { + *p->codeptr++ = 0x66; + *p->codeptr++ = 0xd1; + x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 7); + } else { + *p->codeptr++ = 0x66; + *p->codeptr++ = 0xc1; + x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 7); + *p->codeptr++ = p->vars[insn->args[2]].s16; + } + } else { + x86_emit_mov_reg_reg(p, 4, p->vars[insn->args[2]].alloc, X86_ECX); - *p->codeptr++ = 0x66; - *p->codeptr++ = 0xd3; - x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 7); + g_print(" sarw %%cl, %%%s\n", + x86_get_regname_16(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x66; + *p->codeptr++ = 0xd3; + x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 7); + } } @@ -352,7 +389,7 @@ void orc_program_x86_register_rules (OrcRuleList *list) { orc_rule_list_register (list, "add_s16", x86_rule_add_s16, NULL, - ORC_RULE_REG_REG); + ORC_RULE_REG_REG | ORC_RULE_REG_IMM); orc_rule_list_register (list, "sub_s16", x86_rule_sub_s16, NULL, ORC_RULE_REG_REG); orc_rule_list_register (list, "mul_s16", x86_rule_mul_s16, NULL, @@ -360,7 +397,7 @@ orc_program_x86_register_rules (OrcRuleList *list) orc_rule_list_register (list, "lshift_s16", x86_rule_lshift_s16, NULL, ORC_RULE_REG_REG); orc_rule_list_register (list, "rshift_s16", x86_rule_rshift_s16, NULL, - ORC_RULE_REG_REG); + ORC_RULE_REG_REG | ORC_RULE_REG_IMM); } diff --git a/orc/orcprogram.c b/orc/orcprogram.c index f13953c..6dcad07 100644 --- a/orc/orcprogram.c +++ b/orc/orcprogram.c @@ -127,8 +127,18 @@ orc_program_assign_rules (OrcProgram *program) int i; for(i=0;i<program->n_insns;i++) { - program->insns[i].rule = orc_rule_list_get (orc_x86_list, - program->insns[i].opcode); + OrcInstruction *insn = program->insns + i; + unsigned int flags; + + insn->rule = orc_rule_list_get (orc_x86_list,insn->opcode); + + flags = insn->rule->flags; + if (flags & ORC_RULE_REG_IMM && + program->vars[insn->args[2]].vartype == ORC_VAR_TYPE_CONST) { + program->insns[i].rule_flag = ORC_RULE_REG_IMM; + } else { + program->insns[i].rule_flag = ORC_RULE_REG_REG; + } } } @@ -249,6 +259,12 @@ orc_program_rewrite_vars (OrcProgram *program) } #endif + /* immediate operand, don't load */ + if (program->insns[j].rule_flag == ORC_RULE_REG_IMM) { + int src2 = program->insns[j].args[2]; + program->vars[src2].alloc = 1; + } + for(i=0;i<program->n_vars;i++){ if (program->vars[i].first_use == j) { if (program->vars[i].alloc) continue; diff --git a/orc/orcprogram.h b/orc/orcprogram.h index d0fb38f..8381af6 100644 --- a/orc/orcprogram.h +++ b/orc/orcprogram.h @@ -78,6 +78,7 @@ struct _OrcInstruction { int args[3]; OrcRule *rule; + unsigned int rule_flag; }; struct _OrcFixup { |