gint32 addr; /* address of emitted instruction */
gint32 first_addr; /* first code address of a tree */
- int reg;
+ gint8 reg1;
+ gint8 reg2;
MonoTypeEnum type;
union {
%term LDLOC LDARG STLOC BR RET RETV ARG CALL
%term ADD SUB MUL
%term BLT BEQ BGE BRTRUE
-%term CONV_I4 CONV_I1 CONV_I2
+%term CONV_I4 CONV_I1 CONV_I2 CONV_I8
#
# we start at stmt
#
tree->data.i = tree->data.i + 8;
}
-# do nothing
-reg: CONV_I4 (reg)
-
reg: CONV_I1 (reg) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_alu_reg_imm (s->code, X86_AND, tree->reg, 0xff);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_imm (s->code, X86_AND, tree->reg1, 0xff);
}
reg: CONV_I2 (reg) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_alu_reg_imm (s->code, X86_AND, tree->reg, 0xffff);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_imm (s->code, X86_AND, tree->reg1, 0xffff);
}
+# do nothing
+reg: CONV_I4 (reg)
+
reg: LDLOC {
switch (tree->type) {
case MONO_TYPE_I1:
- x86_widen_membase (s->code, tree->reg, X86_EBP,
+ x86_widen_membase (s->code, tree->reg1, X86_EBP,
tree->data.i, TRUE, FALSE);
break;
case MONO_TYPE_U1:
case MONO_TYPE_BOOLEAN:
- x86_widen_membase (s->code, tree->reg, X86_EBP,
+ x86_widen_membase (s->code, tree->reg1, X86_EBP,
tree->data.i, FALSE, FALSE);
break;
case MONO_TYPE_I2:
- x86_widen_membase (s->code, tree->reg, X86_EBP,
+ x86_widen_membase (s->code, tree->reg1, X86_EBP,
tree->data.i, TRUE, TRUE);
break;
case MONO_TYPE_U2:
case MONO_TYPE_CHAR:
- x86_widen_membase (s->code, tree->reg, X86_EBP,
+ x86_widen_membase (s->code, tree->reg1, X86_EBP,
tree->data.i, FALSE, TRUE);
break;
case MONO_TYPE_CLASS:
case MONO_TYPE_STRING:
case MONO_TYPE_PTR:
- x86_mov_reg_membase (s->code, tree->reg, X86_EBP,
+ x86_mov_reg_membase (s->code, tree->reg1, X86_EBP,
tree->data.i, 4);
break;
default:
} cost {
MBCOND (tree->type != MONO_TYPE_R4 &&
tree->type != MONO_TYPE_R8 &&
- tree->type != MONO_TYPE_I8);
+ tree->type != MONO_TYPE_I8 &&
+ tree->type != MONO_TYPE_U8);
return 1;
}
case MONO_TYPE_CLASS:
case MONO_TYPE_STRING:
case MONO_TYPE_PTR:
- x86_mov_reg_membase (s->code, tree->reg, X86_EBP,
+ x86_mov_reg_membase (s->code, tree->reg1, X86_EBP,
tree->data.i + 8, 4);
break;
default:
} cost {
MBCOND (tree->type != MONO_TYPE_R4 &&
tree->type != MONO_TYPE_R8 &&
- tree->type != MONO_TYPE_I8);
+ tree->type != MONO_TYPE_I8 &&
+ tree->type != MONO_TYPE_U8);
return 1;
}
reg: MUL (reg, reg) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_imul_reg_reg (s->code, tree->reg, tree->right->reg);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_imul_reg_reg (s->code, tree->reg1, tree->right->reg1);
}
reg: ADD (reg, CONST_I4) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_alu_reg_imm (s->code, X86_ADD, tree->reg, tree->right->data.i);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, tree->right->data.i);
}
reg: ADD (reg, reg) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_alu_reg_reg (s->code, X86_ADD, tree->reg, tree->right->reg);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
}
reg: SUB (reg, CONST_I4) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_alu_reg_imm (s->code, X86_SUB, tree->reg, tree->right->data.i);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_imm (s->code, X86_SUB, tree->reg1, tree->right->data.i);
}
reg: SUB (reg, reg) {
- if (tree->reg != tree->left->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->left->reg, 4);
- x86_alu_reg_reg (s->code, X86_SUB, tree->reg, tree->right->reg);
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_reg (s->code, X86_SUB, tree->reg1, tree->right->reg1);
}
stmt: STLOC (CONST_I4) {
case MONO_TYPE_U1:
case MONO_TYPE_BOOLEAN:
x86_mov_membase_reg (s->code, X86_EBP, tree->data.i,
- tree->left->reg, 1);
+ tree->left->reg1, 1);
break;
case MONO_TYPE_I2:
case MONO_TYPE_U2:
case MONO_TYPE_CHAR:
x86_mov_membase_reg (s->code, X86_EBP, tree->data.i,
- tree->left->reg, 2);
+ tree->left->reg1, 2);
break;
case MONO_TYPE_I:
case MONO_TYPE_I4:
case MONO_TYPE_STRING:
case MONO_TYPE_PTR:
x86_mov_membase_reg (s->code, X86_EBP, tree->data.i,
- tree->left->reg, 4);
+ tree->left->reg1, 4);
break;
default:
g_warning ("unknown type %02x", tree->type);
gint32 offset;
tree->is_jump = 1;
- x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg, tree->right->data.i);
+ x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
offset = 6 + s->code - start;
x86_branch32 (s->code, X86_CC_LT, tree->data.i - offset, TRUE);
}
gint32 offset;
tree->is_jump = 1;
- x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg, tree->right->data.i);
+ x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
offset = 6 + s->code - start;
x86_branch32 (s->code, X86_CC_EQ, tree->data.i - offset, TRUE);
}
gint32 offset;
tree->is_jump = 1;
- x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg, tree->right->data.i);
+ x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
offset = 6 + s->code - start;
x86_branch32 (s->code, X86_CC_GE, tree->data.i - offset, TRUE);
}
gint32 offset;
tree->is_jump = 1;
- x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg, 0);
+ x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
offset = 6 + s->code - start;
x86_branch32 (s->code, X86_CC_NE, tree->data.i - offset, TRUE);
}
x86_jump32 (s->code, tree->data.i - 5);
}
- g_assert (tree->left->reg == X86_EAX); // return must be in EAX
+ g_assert (tree->left->reg1 == X86_EAX); // return must be in EAX
}
stmt: RET {
}
stmt: ARG (reg) {
- x86_push_reg (s->code, tree->left->reg);
+ x86_push_reg (s->code, tree->left->reg1);
}
reg: CALL {
x86_mov_reg_imm (s->code, X86_EAX, tree->data.p);
x86_call_membase (s->code, X86_EAX,
G_STRUCT_OFFSET (MonoMethod, addr));
- g_assert (tree->reg == X86_EAX);
+ g_assert (tree->reg1 == X86_EAX);
break;
default:
g_warning ("unknown type %02x", tree->type);
} cost {
MBCOND (tree->type != MONO_TYPE_R4 &&
tree->type != MONO_TYPE_R8 &&
- tree->type != MONO_TYPE_I8);
+ tree->type != MONO_TYPE_I8 &&
+ tree->type != MONO_TYPE_U8);
return 1;
}
x86_call_membase (s->code, X86_EAX, G_STRUCT_OFFSET (MonoMethod, addr));
}
+#
+# 64 bit integers
+#
+
+lreg: CONV_I8 (CONST_I4) {
+ x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
+
+ if (tree->left->data.i >= 0)
+ x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
+ else
+ x86_mov_reg_imm (s->code, tree->reg1, -1);
+}
+
+stmt: STLOC (lreg) {
+ x86_mov_membase_reg (s->code, X86_EBP, tree->data.i,
+ tree->left->reg1, 4);
+ x86_mov_membase_reg (s->code, X86_EBP, tree->data.i + 4,
+ tree->left->reg2, 4);
+}
+
+lreg: LDARG {
+ x86_mov_reg_membase (s->code, tree->reg1, X86_EBP,
+ tree->data.i + 8, 4);
+ x86_mov_reg_membase (s->code, tree->reg2, X86_EBP,
+ tree->data.i + 8 + 4, 4);
+} cost {
+ MBCOND (tree->type == MONO_TYPE_I8 ||
+ tree->type == MONO_TYPE_U8);
+ return 0;
+}
+
+lreg: LDLOC {
+ x86_mov_reg_membase (s->code, tree->reg1, X86_EBP,
+ tree->data.i, 4);
+ x86_mov_reg_membase (s->code, tree->reg2, X86_EBP,
+ tree->data.i + 4, 4);
+} cost {
+ MBCOND (tree->type == MONO_TYPE_I8 ||
+ tree->type == MONO_TYPE_U8);
+ return 0;
+}
+
+lreg: SUB (lreg, lreg) {
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ if (tree->reg2 != tree->left->reg2)
+ x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
+ x86_alu_reg_reg (s->code, X86_SUB, tree->reg1, tree->right->reg1);
+ x86_alu_reg_reg (s->code, X86_SUB, tree->reg2, tree->right->reg2);
+}
+
+lreg: ADD (lreg, lreg) {
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ if (tree->reg2 != tree->left->reg2)
+ x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
+ x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
+ x86_alu_reg_reg (s->code, X86_ADC, tree->reg2, tree->right->reg2);
+}
+
+lreg: CALL {
+ x86_mov_reg_imm (s->code, X86_EAX, tree->data.p);
+ x86_call_membase (s->code, X86_EAX,
+ G_STRUCT_OFFSET (MonoMethod, addr));
+} cost {
+ MBCOND (tree->type == MONO_TYPE_I8 ||
+ tree->type == MONO_TYPE_U8);
+ return 0;
+}
+
+stmt: RETV (lreg) {
+
+ if (!tree->last_instr) {
+ tree->is_jump = 1;
+ x86_jump32 (s->code, tree->data.i - 5);
+ }
+ g_assert (tree->left->reg1 == X86_EAX); // return must be in EAX
+ g_assert (tree->left->reg2 == X86_EDX); // return must be in EDX
+}
+
+
+stmt: ARG (lreg) {
+ x86_push_reg (s->code, tree->left->reg2);
+ x86_push_reg (s->code, tree->left->reg1);
+}
+
+stmt: BEQ (lreg, lreg) {
+ guint8 *start = s->code;
+ gint32 o1, o2, i;
+
+ tree->is_jump = 1;
+
+ for (i = 0; i < 2; i ++) {
+ s->code = start;
+ x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
+ o1 = 2 + s->code - start;
+ x86_branch8 (s->code, X86_CC_NE, o2 - o1, FALSE);
+ x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
+ o2 = 6 + s->code - start;
+ x86_branch32 (s->code, X86_CC_EQ, tree->data.i - o2, TRUE);
+ }
+}
+stmt: BGE (lreg, lreg) {
+ guint8 *start = s->code;
+ gint32 o1, o2, oe, i;
+
+ tree->is_jump = 1;
+
+ for (i = 0; i < 2; i ++) {
+ s->code = start;
+ x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
+ o1 = 6 + s->code - start;
+ x86_branch32 (s->code, X86_CC_GT, tree->data.i - o1, TRUE);
+ x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg2, tree->right->reg2);
+ o2 = 2 + s->code - start;
+ x86_branch8 (s->code, X86_CC_NE, oe - o2, TRUE);
+ x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
+ oe = 6 + s->code - start;
+ x86_branch32 (s->code, X86_CC_GE, tree->data.i - oe, FALSE);
+ }
+}
+
#
# floating point
# fixme: dont know how to assign registers?
tree->is_jump = 1;
x86_jump32 (s->code, tree->data.i - 5);
}
-
- //g_assert (tree->left->reg == X86_EAX); // return must be in EAX
}
#
reg: ADD (locaddr, reg) {
- if (tree->reg != tree->right->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->right->reg, 4);
- x86_alu_reg_membase (s->code, X86_ADD, tree->reg, X86_EBP,
+ if (tree->reg1 != tree->right->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->right->reg1, 4);
+ x86_alu_reg_membase (s->code, X86_ADD, tree->reg1, X86_EBP,
tree->left->data.i);
} cost {
MBCOND (tree->left->type == MONO_TYPE_I4 ||
}
reg: MUL (locaddr, reg) {
- if (tree->reg != tree->right->reg)
- x86_mov_reg_reg (s->code, tree->reg, tree->right->reg, 4);
- x86_imul_reg_membase (s->code, tree->reg, X86_EBP, tree->left->data.i);
+ if (tree->reg1 != tree->right->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->right->reg1, 4);
+ x86_imul_reg_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i);
} cost {
MBCOND (tree->left->type == MONO_TYPE_I4 ||
tree->left->type == MONO_TYPE_U4);