summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/InstrSelection.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-11 22:29:53 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-11 22:29:53 +0000
commit0bec4f557a96e1a40437cf5af20cc78a5eec8a63 (patch)
treec1e05ec804c43aa5a8f5f21b0ed02d0587d29563 /compiler_and_linker/unsorted/InstrSelection.c
parentaec1b8dddc68ecb8288ec6132932e4c7b4bca09f (diff)
downloadMWCC-0bec4f557a96e1a40437cf5af20cc78a5eec8a63.tar.gz
MWCC-0bec4f557a96e1a40437cf5af20cc78a5eec8a63.zip
getting closer
Diffstat (limited to 'compiler_and_linker/unsorted/InstrSelection.c')
-rw-r--r--compiler_and_linker/unsorted/InstrSelection.c991
1 files changed, 770 insertions, 221 deletions
diff --git a/compiler_and_linker/unsorted/InstrSelection.c b/compiler_and_linker/unsorted/InstrSelection.c
index 1916711..0ea8bf9 100644
--- a/compiler_and_linker/unsorted/InstrSelection.c
+++ b/compiler_and_linker/unsorted/InstrSelection.c
@@ -139,7 +139,7 @@ void gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *ou
output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_FPR();
emitpcode(PC_FMR, output->reg, objReg);
fval = one_point_zero;
- load_floating_constant(constReg = ALLOC_FPR(), type, &fval.value);
+ load_floating_constant(constReg = ALLOC_FPR(), type, &fval);
if (ENODE_IS(expr, EPOSTINC)) {
emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, objReg, objReg, constReg);
@@ -157,7 +157,7 @@ void gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *ou
emitpcode(PC_FMR, output->reg, b.reg);
fval = one_point_zero;
- load_floating_constant(constReg = ALLOC_FPR(), type, &fval.value);
+ load_floating_constant(constReg = ALLOC_FPR(), type, &fval);
finalReg = ALLOC_FPR();
if (ENODE_IS(expr, EPOSTINC))
@@ -2907,351 +2907,340 @@ void gen_condition(ENode *cond, Operand *output) {
void gen_condition_gpr(ENode *cond, Operand *output, short outputReg) {
ENode *left;
ENode *right;
- Operand op1;
+ Operand condOp;
+ int finalReg;
int tmpReg;
- int reg;
+ int tmpReg2;
+ int tmpReg3;
+ int tmpReg4;
int a;
int b;
left = cond->data.diadic.left;
right = cond->data.diadic.right;
- memclrw(&op1, sizeof(Operand));
+ memclrw(&condOp, sizeof(Operand));
if (!IS_TYPE_FLOAT(left->rtype)) {
+ Operand op1;
Operand op2;
- Operand op3;
- Operand op4;
+ Operand opTmp;
+ memclrw(&op1, sizeof(Operand));
memclrw(&op2, sizeof(Operand));
- memclrw(&op3, sizeof(Operand));
- memclrw(&op4, sizeof(Operand));
+ memclrw(&opTmp, sizeof(Operand));
if (right->hascall) {
- GEN_NODE(right, &op3);
+ GEN_NODE(right, &op2);
if (!IS_INT_CONST_ZERO(right)) {
if (right->rtype->size < 4)
- extend32(&op3, right->rtype, 0);
- ENSURE_GPR(&op3, right->rtype, 0);
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
}
- GEN_NODE(left, &op2);
+ GEN_NODE(left, &op1);
if (left->rtype->size < 4)
- extend32(&op2, left->rtype, 0);
- ENSURE_GPR(&op2, left->rtype, 0);
+ extend32(&op1, left->rtype, 0);
+ ENSURE_GPR(&op1, left->rtype, 0);
} else {
- GEN_NODE(left, &op2);
- ENSURE_GPR(&op2, left->rtype, 0);
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
if (left->rtype->size < 4)
- extend32(&op2, left->rtype, 0);
+ extend32(&op1, left->rtype, 0);
- GEN_NODE(right, &op3);
+ GEN_NODE(right, &op2);
if (!IS_INT_CONST_ZERO(right)) {
if (right->rtype->size < 4)
- extend32(&op3, right->rtype, 0);
- ENSURE_GPR(&op3, right->rtype, 0);
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
}
}
switch (cond->type) {
case EEQU:
if (
- copts.peephole &&
- IS_INT_CONST(right) &&
- pclastblock->pcodeCount > 0) {
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
PCode *pc = pclastblock->lastPCode;
- if (pc->op == PC_RLWINM && pc->args[0].data.reg.reg == op2.reg) {
- SInt32 r6 = pc->args[2].data.imm.value;
- SInt32 r7 = pc->args[3].data.imm.value;
- SInt32 r3 = right->data.intval.lo;
- if (r7 == pc->args[4].data.imm.value) {
- reg = outputReg ? outputReg : ALLOC_GPR();
- if (r3 != (r3 & 1)) {
- emitpcode(PC_LI, reg, 0);
- } else if (r3 == 0) {
- int tmpreg = ALLOC_GPR();
- emitpcode(
- PC_RLWINM, tmpreg,
- pc->args[1].data.reg.reg,
- (r6 + r7 + 1) & 31, 31, 31);
- emitpcode(PC_XORI, reg, tmpreg, 1);
- } else if (r3 == 1) {
- emitpcode(
- PC_RLWINM, reg,
- pc->args[1].data.reg.reg,
- (r6 + r7 + 1) & 31, 31, 31);
- } else {
- CError_FATAL(5434);
- }
- output->optype = OpndType_GPR;
- output->reg = reg;
- return;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, 0);
+ } else if (value == 0) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
+ } else if (value == 1) {
+ emitpcode(
+ PC_RLWINM, finalReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ } else {
+ CError_FATAL(5434);
}
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
}
}
if (IS_INT_CONST_ZERO(right)) {
- //int tmpReg = ALLOC_GPR(); // affected
- int tmpReg;
- int t = used_virtual_registers[RegClass_GPR];
- used_virtual_registers[RegClass_GPR]++;
- emitpcode(PC_CNTLZW, t, op2.reg, 0);
- tmpReg = t;
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg, 27, 5, 31);
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg, op1.reg, 0);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg, 27, 5, 31);
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
} else {
- int tmpReg, tmpReg2;
- tmpReg = ALLOC_GPR(); // affected
- emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
tmpReg2 = ALLOC_GPR();
emitpcode(PC_CNTLZW, tmpReg2, tmpReg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg2, 27, 5, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg2, 27, 5, 31);
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
case ENOTEQU:
if (
- copts.peephole &&
- IS_INT_CONST(right) &&
- pclastblock->pcodeCount > 0) {
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
PCode *pc = pclastblock->lastPCode;
- if (pc->op == PC_RLWINM && pc->args[0].data.reg.reg == op2.reg) {
- SInt32 r6 = pc->args[2].data.imm.value;
- SInt32 r7 = pc->args[3].data.imm.value;
- SInt32 r3 = right->data.intval.lo;
- if (r7 == pc->args[4].data.imm.value) {
- reg = outputReg ? outputReg : ALLOC_GPR();
- if (r3 != (r3 & 1)) {
- emitpcode(PC_LI, reg, 1);
- } else if (r3 == 0) {
- emitpcode(
- PC_RLWINM, reg,
- pc->args[1].data.reg.reg,
- (r6 + r7 + 1) & 31, 31, 31);
- } else if (r3 == 1) {
- int tmpreg = ALLOC_GPR(); // affected
- emitpcode(
- PC_RLWINM, tmpreg,
- pc->args[1].data.reg.reg,
- (r6 + r7 + 1) & 31, 31, 31);
- emitpcode(PC_XORI, reg, tmpreg, 1);
- } else {
- CError_FATAL(5503);
- }
- output->optype = OpndType_GPR;
- output->reg = reg;
- return;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, 1);
+ } else if (value == 0) {
+ emitpcode(
+ PC_RLWINM, finalReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ } else if (value == 1) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
+ } else {
+ CError_FATAL(5503);
}
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
}
}
if (IS_INT_CONST_ZERO(right)) {
if (copts.optimize_for_size) {
- int tmpReg;
- tmpReg = ALLOC_GPR(); // affected
- emitpcode(PC_ADDIC, tmpReg, op2.reg, -1);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_SUBFE, reg, tmpReg, op2.reg);
- } else {
- int tmpReg, tmpReg2;
- // tmpReg, tmpReg2 swap
- tmpReg = ALLOC_GPR();
- emitpcode(PC_NEG, tmpReg, op2.reg);
- tmpReg2 = ALLOC_GPR();
- emitpcode(PC_OR, tmpReg2, tmpReg, op2.reg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg2, 1, 31, 31);
- }
- output->optype = OpndType_GPR;
- output->reg = reg;
- return;
- } else {
- if (copts.optimize_for_size) {
- int tmpReg, tmpReg2;
- // tmpReg, tmpReg2 swap
tmpReg = ALLOC_GPR();
- emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
- tmpReg2 = ALLOC_GPR();
- emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_SUBFE, reg, tmpReg2, tmpReg);
+ emitpcode(PC_ADDIC, tmpReg, op1.reg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, op1.reg);
} else {
- int tmpReg, tmpReg2, tmpReg3;
- // tmpReg, tmpReg2 swap
tmpReg = ALLOC_GPR();
- emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ emitpcode(PC_NEG, tmpReg, op1.reg);
tmpReg2 = ALLOC_GPR();
- emitpcode(PC_SUBF, tmpReg2, op3.reg, op2.reg);
- tmpReg3 = ALLOC_GPR();
- emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg3, 1, 31, 31);
+ emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31);
}
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
+ if (copts.optimize_for_size) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op2.reg, op1.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
case EGREATEREQU:
if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
- int tmpReg;
tmpReg = ALLOC_GPR();
- emitpcode(PC_RLWINM, tmpReg, op2.reg, 1, 31, 31);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_XORI, reg, tmpReg, 1);
+ emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
- op4 = op3;
- op3 = op2;
- op2 = op4;
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
case ELESSEQU:
if (is_unsigned(left->rtype)) {
if (copts.optimize_for_size) {
- int tmpReg, tmpReg2;
tmpReg = ALLOC_GPR();
emitpcode(PC_LI, tmpReg, -1);
tmpReg2 = ALLOC_GPR();
- emitpcode(PC_SUBFC, tmpReg2, op2.reg, op3.reg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_SUBFZE, reg, tmpReg);
+ emitpcode(PC_SUBFC, tmpReg2, op1.reg, op2.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFZE, finalReg, tmpReg);
} else {
- int tmpReg, tmpReg2, tmpReg3, tmpReg4;
tmpReg = ALLOC_GPR();
- emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
tmpReg2 = ALLOC_GPR();
- emitpcode(PC_ORC, tmpReg2, op3.reg, op2.reg);
+ emitpcode(PC_ORC, tmpReg2, op2.reg, op1.reg);
tmpReg3 = ALLOC_GPR();
emitpcode(PC_RLWINM, tmpReg3, tmpReg, 31, 1, 31);
tmpReg4 = ALLOC_GPR();
emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg4, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31);
}
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
if (IS_INT_CONST_ZERO(right)) {
- int tmpReg, tmpReg2;
tmpReg = ALLOC_GPR();
emitpcode(PC_LI, tmpReg, 1);
tmpReg2 = ALLOC_GPR();
- emitpcode(PC_CNTLZW, tmpReg2, op2.reg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWNM, reg, tmpReg, tmpReg2, 31, 31);
- output->optype = OpndType_GPR;
- output->reg = reg;
- return;
- } else {
- int tmpReg, tmpReg2, tmpReg3;
- tmpReg2 = ALLOC_GPR();
- emitpcode(PC_SRAWI, tmpReg2, op3.reg, 31);
- tmpReg = ALLOC_GPR();
- emitpcode(PC_RLWINM, tmpReg, op2.reg, 1, 31, 31);
- tmpReg3 = ALLOC_GPR();
- emitpcode(PC_SUBFC, tmpReg3, op2.reg, op3.reg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_ADDE, reg, tmpReg2, tmpReg);
+ emitpcode(PC_CNTLZW, tmpReg2, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWNM, finalReg, tmpReg, tmpReg2, 31, 31);
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpReg2, op2.reg, 31);
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg3, op1.reg, op2.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_ADDE, finalReg, tmpReg2, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
case EGREATER:
if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
- int tmpReg, tmpReg2;
tmpReg = ALLOC_GPR();
- emitpcode(PC_NEG, tmpReg, op2.reg);
+ emitpcode(PC_NEG, tmpReg, op1.reg);
tmpReg2 = ALLOC_GPR();
- emitpcode(PC_ANDC, tmpReg2, tmpReg, op2.reg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg2, 1, 31, 31);
+ emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31);
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
- op4 = op3;
- op3 = op2;
- op2 = op4;
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
case ELESS:
if (is_unsigned(left->rtype)) {
if (left->rtype->size <= 2) {
- int tmpReg;
tmpReg = ALLOC_GPR();
- emitpcode(PC_SUBF, tmpReg, op3.reg, op2.reg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg, 1, 31, 31);
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg, 1, 31, 31);
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
} else {
if (copts.optimize_for_size) {
- int tmpReg, tmpReg2;
tmpReg = ALLOC_GPR();
- emitpcode(PC_SUBFC, tmpReg, op3.reg, op2.reg);
+ emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg);
tmpReg2 = ALLOC_GPR();
emitpcode(PC_SUBFE, tmpReg2, tmpReg, tmpReg);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_NEG, reg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, finalReg, tmpReg2);
} else {
- int tmpReg, tmpReg2, tmpReg3;
tmpReg = ALLOC_GPR();
- emitpcode(PC_XOR, tmpReg, op3.reg, op2.reg);
+ emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg);
tmpReg2 = ALLOC_GPR();
emitpcode(PC_CNTLZW, tmpReg2, tmpReg);
tmpReg3 = ALLOC_GPR();
- emitpcode(PC_SLW, tmpReg3, op3.reg, tmpReg2);
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg3, 1, 31, 31);
+ emitpcode(PC_SLW, tmpReg3, op2.reg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31);
}
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
return;
}
return;
- } else {
- if (IS_INT_CONST_ZERO(right)) {
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, op2.reg, 1, 31, 31);
- output->optype = OpndType_GPR;
- output->reg = reg;
- return;
- } else {
- int tmpReg, tmpReg2, tmpReg3, tmpReg4;
- tmpReg = ALLOC_GPR();
- emitpcode(PC_XOR, tmpReg, op3.reg, op2.reg);
- tmpReg2 = ALLOC_GPR();
- emitpcode(PC_SRAWI, tmpReg2, tmpReg, 1);
- tmpReg3 = ALLOC_GPR();
- emitpcode(PC_AND, tmpReg3, tmpReg, op3.reg);
- tmpReg4 = ALLOC_GPR();
- emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
+ }
- reg = outputReg ? outputReg : ALLOC_GPR();
- emitpcode(PC_RLWINM, reg, tmpReg4, 1, 31, 31);
- output->optype = OpndType_GPR;
- output->reg = reg;
- return;
- }
+ if (IS_INT_CONST_ZERO(right)) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, op1.reg, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
}
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpReg2, tmpReg, 1);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_AND, tmpReg3, tmpReg, op2.reg);
+ tmpReg4 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
+
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
default:
CError_FATAL(5777);
}
}
- gen_condition(cond, &op1);
+ gen_condition(cond, &condOp);
emitpcode(PC_MFCR, tmpReg = used_virtual_registers[RegClass_GPR]++);
a = 0;
- b = op1.reg * 4;
- switch (op1.regOffset) {
+ b = condOp.reg * 4;
+ switch (condOp.regOffset) {
case ENOTEQU:
a = 1;
case EEQU:
@@ -3267,18 +3256,349 @@ void gen_condition_gpr(ENode *cond, Operand *output, short outputReg) {
break;
}
- reg = outputReg ? outputReg : ALLOC_GPR();
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
if (a) {
emitpcode(PC_RLWINM, tmpReg, tmpReg, b + 1, 31, 31);
- emitpcode(PC_XORI, reg, tmpReg, 1);
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
} else {
- emitpcode(PC_RLWINM, reg, tmpReg, b + 1, 31, 31);
+ emitpcode(PC_RLWINM, finalReg, tmpReg, b + 1, 31, 31);
}
output->optype = OpndType_GPR;
- output->reg = reg;
+ output->reg = finalReg;
}
void gen_negated_condition_gpr(ENode *cond, Operand *output, short outputReg) {
+ ENode *left;
+ ENode *right;
+ Operand op1;
+ Operand op2;
+ Operand opTmp;
+ int finalReg;
+ int tmpReg;
+ int tmpReg2;
+ int tmpReg3;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ CError_ASSERT(5843, TYPE_FITS_IN_REGISTER(left->rtype) && TYPE_FITS_IN_REGISTER(right->rtype));
+
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+ memclrw(&opTmp, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &op2);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+
+ GEN_NODE(left, &op1);
+ if (left->rtype->size < 4)
+ extend32(&op1, left->rtype, 0);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ if (left->rtype->size < 4)
+ extend32(&op1, left->rtype, 0);
+
+ GEN_NODE(right, &op2);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+ }
+
+ switch (cond->type) {
+ case EEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
+ PCode *pc = pclastblock->lastPCode;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, 0);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 0) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 1) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM,
+ tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31,
+ 31,
+ 31);
+ emitpcode(PC_NEG, finalReg, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = tmpReg; // bug???
+ return;
+ }
+
+ CError_FATAL(5923);
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ if (copts.optimize_for_size) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg, op1.reg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg2, tmpReg, 27, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, finalReg, tmpReg2);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (copts.optimize_for_size) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_NOR, tmpReg3, tmpReg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg3, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case ENOTEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
+ PCode *pc = pclastblock->lastPCode;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 0) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_NEG, finalReg, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 1) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ CError_FATAL(6031);
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ if (copts.optimize_for_size) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFIC, tmpReg, op1.reg, 0);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg2, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (copts.optimize_for_size) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBFIC, tmpReg2, tmpReg, 0);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg3, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case EGREATEREQU:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
+ case ELESSEQU:
+ if (is_unsigned(left->rtype)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDZE, tmpReg2, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBF, finalReg, tmpReg2, op1.reg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ORC, tmpReg2, op1.reg, tmpReg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg2, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XORIS, tmpReg, op1.reg, 0x8000);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_ADDC, tmpReg3, tmpReg2, tmpReg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg3);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case EGREATER:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg2, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
+ case ELESS:
+ if (is_unsigned(left->rtype)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, op1.reg, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg2, op2.reg, 1, 31, 31);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg3, op1.reg, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg2);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ default:
+ CError_FATAL(6240);
+ }
}
void compare_floating(short nt, ENode *left, ENode *right, Operand *output) {
@@ -3347,9 +3667,127 @@ void compare_integer(short nt, ENode *left, ENode *right, Operand *output) {
}
void compare_immediate(short nt, ENode *left, SInt32 value, Operand *output) {
+ int postIncFlag;
+ short postIncReg;
+ Operand op;
+ SInt32 postIncValue;
+
+ memclrw(&op, sizeof(Operand));
+
+ postIncFlag = ispostincrementopportunity(left, &op, &postIncValue);
+ if (!postIncFlag) {
+ GEN_NODE(left, &op);
+ if (op.optype != OpndType_CRField) {
+ if (left->rtype->size < 4)
+ extend32(&op, left->rtype, 0);
+ else
+ ENSURE_GPR(&op, left->rtype, 0);
+ }
+ } else {
+ postIncReg = op.reg;
+ if (left->rtype->size < 4)
+ extend32(&op, left->rtype, 0);
+ ENSURE_GPR(&op, left->rtype, 0);
+ }
+
+ if (op.optype == OpndType_CRField) {
+ if (
+ (nt == EEQU && value == 1) ||
+ (nt == ENOTEQU && value == 0) ||
+ (nt == EGREATER && value == 0) ||
+ (nt == EGREATEREQU && value == 1)
+ )
+ {
+ *output = op;
+ return;
+ }
+
+ if (
+ (nt == EEQU && value == 0) ||
+ (nt == ENOTEQU && value == 1) ||
+ (nt == ELESS && value == 1) ||
+ (nt == ELESSEQU && value == 0)
+ )
+ {
+ *output = op;
+ switch (op.regOffset) {
+ case EEQU:
+ output->regOffset = ENOTEQU;
+ return;
+ case ENOTEQU:
+ output->regOffset = EEQU;
+ return;
+ case ELESS:
+ output->regOffset = EGREATEREQU;
+ return;
+ case EGREATER:
+ output->regOffset = ELESSEQU;
+ return;
+ case ELESSEQU:
+ output->regOffset = EGREATER;
+ return;
+ case EGREATEREQU:
+ output->regOffset = ELESS;
+ return;
+ }
+ }
+
+ ENSURE_GPR(&op, left->rtype, 0);
+ }
+
+ if (
+ copts.peephole &&
+ value == 0 &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op != PC_RLWINM &&
+ (PCODE_FLAG_SET_F(pclastblock->lastPCode) & (fIsMove | fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op.reg &&
+ (!is_unsigned(left->rtype) || nt == EEQU || nt == ENOTEQU)
+ )
+ {
+ pcsetrecordbit(pclastblock->lastPCode);
+ } else {
+ emitpcode(is_unsigned(left->rtype) ? PC_CMPLI : PC_CMPI, 0, op.reg, value);
+ }
+
+ if (postIncFlag)
+ add_register_immediate(postIncReg, postIncReg, postIncValue);
+
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = nt;
}
void compare_immediate_long(short nt, ENode *left, SInt32 value, Operand *output) {
+ int postIncFlag;
+ short postIncReg;
+ int outputReg;
+ Operand op;
+ SInt32 postIncValue;
+
+ memclrw(&op, sizeof(Operand));
+
+ postIncFlag = ispostincrementopportunity(left, &op, &postIncValue);
+ if (!postIncFlag) {
+ GEN_NODE(left, &op);
+ } else {
+ postIncReg = op.reg;
+ }
+
+ if (left->rtype->size < 4)
+ extend32(&op, left->rtype, 0);
+ ENSURE_GPR(&op, left->rtype, 0);
+
+ outputReg = ALLOC_GPR();
+ emitpcode(PC_ADDIS, outputReg, op.reg, 0, (SInt16) (~(value >> 16) + 1));
+ emitpcode(PC_CMPLI, 0, outputReg, value & 0xFFFF);
+
+ if (postIncFlag)
+ add_register_immediate(postIncReg, postIncReg, postIncValue);
+
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = nt;
}
static int ismask(SInt32 value, short *first, short *last) {
@@ -3729,12 +4167,123 @@ void I8_gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output
}
void I8_gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ }
+
+ CError_ASSERT(7254, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ emitpcode(PC_XOR, reg, opleft.reg, opright.reg);
+ emitpcode(PC_XOR, regHi, opleft.regHi, opright.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
}
void I8_gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ }
+
+ CError_ASSERT(7304, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ emitpcode(PC_OR, reg, opleft.reg, opright.reg);
+ emitpcode(PC_OR, regHi, opleft.regHi, opright.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
}
void I8_gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ }
+
+ CError_ASSERT(7354, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ emitpcode(PC_AND, reg, opleft.reg, opright.reg);
+ emitpcode(PC_AND, regHi, opleft.regHi, opright.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
}
int I8_getbit(UInt64 val) {
@@ -4173,7 +4722,7 @@ void I8_gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output
if (ENODE_IS(left, EINDIRECT))
left = left->data.monadic;
else
- CError_FATAL(8238);
+ CError_FATAL(8328);
right = expr->data.cond.expr2;
} else {
left = expr->data.diadic.left;