summaryrefslogtreecommitdiff
path: root/orc/orcrules-x86.c
diff options
context:
space:
mode:
Diffstat (limited to 'orc/orcrules-x86.c')
-rw-r--r--orc/orcrules-x86.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/orc/orcrules-x86.c b/orc/orcrules-x86.c
new file mode 100644
index 0000000..4becb48
--- /dev/null
+++ b/orc/orcrules-x86.c
@@ -0,0 +1,146 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <orc/orcprogram.h>
+#include <orc/x86.h>
+
+#define SIZE 65536
+
+/* rules */
+
+static void
+x86_rule_loadi_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ x86_emit_mov_imm_reg (p, 2, p->vars[insn->args[2]].s16,
+ p->vars[insn->args[0]].alloc);
+}
+
+static void
+x86_rule_add_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ if (insn->rule_flag == ORC_RULE_REG_IMM) {
+ int value = p->vars[insn->args[2]].s16;
+ printf(" 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 {
+ printf(" 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
+x86_rule_sub_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ printf(" subw %%%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++ = 0x2b;
+ x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc,
+ p->vars[insn->args[0]].alloc);
+}
+
+static void
+x86_rule_mul_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ printf(" imulw %%%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++ = 0x0f;
+ *p->codeptr++ = 0xaf;
+ x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc,
+ p->vars[insn->args[0]].alloc);
+}
+
+static void
+x86_rule_lshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ x86_emit_mov_reg_reg(p, 4, p->vars[insn->args[2]].alloc, X86_ECX);
+
+ printf(" shlw %%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, 4);
+}
+
+static void
+x86_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ if (insn->rule_flag == ORC_RULE_REG_IMM) {
+ printf(" sarw $%d, %%%s\n",
+ p->vars[insn->args[2]].s16,
+ 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);
+
+ printf(" 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);
+ }
+}
+
+
+void
+orc_program_x86_register_rules (void)
+{
+ orc_rule_register ("_loadi_s16", ORC_RULE_SCALAR_1, x86_rule_loadi_s16, NULL,
+ ORC_RULE_REG_IMM);
+
+ orc_rule_register ("add_s16", ORC_RULE_SCALAR_1, x86_rule_add_s16, NULL,
+ ORC_RULE_REG_REG | ORC_RULE_REG_IMM);
+ orc_rule_register ("sub_s16", ORC_RULE_SCALAR_1, x86_rule_sub_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("mul_s16", ORC_RULE_SCALAR_1, x86_rule_mul_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("lshift_s16", ORC_RULE_SCALAR_1, x86_rule_lshift_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("rshift_s16", ORC_RULE_SCALAR_1, x86_rule_rshift_s16, NULL,
+ ORC_RULE_REG_REG | ORC_RULE_REG_IMM);
+}
+