/* * Unable to convert to OREG (notoff() returned failure). Output * suitable instructions to replace OREG. */ void myormake(NODE *q) { NODE *p; if (x2debug) printf("myormake(%p)\n", q); p = q->n_left; /* * This handles failed OREGs conversions, due to the offset * being too large for an OREG. */ if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); if (isreg(p->n_right) == 0) (void)geninsn(p->n_right, INAREG); (void)geninsn(p, INAREG); } else if (p->n_op == REG) { q->n_op = OREG; q->n_lval = p->n_lval; q->n_rval = p->n_rval; tfree(p); } }
/* setup for assignment operator */ int setasg(NODE *p, int cookie) { if (x2debug) printf("setasg(%p,%s)\n", p, prcook(cookie)); if (p->n_left->n_op == FLD && !isreg(p->n_left->n_left)) { NODE *l, *r; int reg; geninsn(p->n_left->n_left, INAREG); reg = DECRA(p->n_left->n_left->n_reg, 0); l = tcopy(p->n_left->n_left); p->n_left->n_left->n_op = REG; p->n_left->n_left->n_rval = reg; p->n_left->n_left->n_lval = 0; r = tcopy(p->n_left->n_left); geninsn(p->n_left, INAREG); l = mkbinode(ASSIGN, l, r, l->n_type); geninsn(l, INAREG); return (1); } return (0); }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. */ void offstar(NODE *p, int shape) { NODE *r; if (x2debug) printf("offstar(%p)\n", p); if (isreg(p)) return; /* Is already OREG */ r = p->n_right; if( p->n_op == PLUS || p->n_op == MINUS ){ if( r->n_op == ICON ){ if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); /* Converted in ormake() */ return; } if (r->n_op == LS && r->n_right->n_op == ICON && getlval(r->n_right) == 2 && p->n_op == PLUS) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); if (isreg(r->n_left) == 0) (void)geninsn(r->n_left, INAREG); return; } } (void)geninsn(p, INAREG); }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. */ void offstar(NODE *p, int shape) { if (x2debug) printf("offstar(%p)\n", p); if (isreg(p)) return; /* Is already OREG */ if (p->n_op == UMUL) p = p->n_left; /* double indexed umul */ if (inctree(p)) /* Do post-inc conversion */ return; if( p->n_op == PLUS || p->n_op == MINUS ){ if (p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); /* Converted in ormake() */ return; } } (void)geninsn(p, INAREG); }
/* * Turn a UMUL-referenced node into OREG. */ void offstar(NODE *p, int shape) { if (x2debug) printf("offstar(%p)\n", p); if (p->n_op == PLUS || p->n_op == MINUS) { if (p->n_right->n_op == ICON) { if (isreg(p->n_left) == 0) (void)geninsn(p->n_left, INAREG); /* Converted in ormake() */ return; } } (void)geninsn(p, INAREG); }
/* * Convert a node to REG or OREG. * Shape is register class where we want the result. * Returns register class if register nodes. * If w is: (should be shapes) * - SRREG - result in register, call geninsn(). * - SROREG - create OREG; call offstar(). * - 0 - clear su, walk down. */ static int swmatch(NODE *p, int shape, int w) { int rv = 0; F2DEBUG(("swmatch: p=%p, shape=%s, w=%s\n", p, prcook(shape), srtyp[w])); switch (w) { case SRREG: rv = geninsn(p, shape); break; case SROREG: /* should be here only if op == UMUL */ if (p->n_op != UMUL && p->n_op != FLD) comperr("swmatch %p", p); if (p->n_op == FLD) { offstar(p->n_left->n_left, shape); p->n_left->n_su = 0; } else offstar(p->n_left, shape); p->n_su = 0; rv = ffs(shape)-1; break; case 0: if (optype(p->n_op) == BITYPE) swmatch(p->n_right, 0, 0); if (optype(p->n_op) != LTYPE) swmatch(p->n_left, 0, 0); p->n_su = 0; } return rv; }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. * * AMD64 (and i386) have a quite powerful addressing scheme: * : 4(%rax) 4 + %rax * : 4(%rbx,%rax,8) 4 + %rbx + %rax * 8 * : 4(,%rax) 4 + %rax * 8 * The 8 above can be 1,2,4 or 8. */ void offstar(NODE *p, int shape) { NODE *l; if (x2debug) { printf("offstar(%p)\n", p); fwalk(p, e2print, 0); } if (isreg(p)) return; /* Matched (%rax) */ if (findls(p, 0)) return; /* Matched (,%rax,8) */ if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { l = p->n_right; if (isreg(l)) return; /* Matched 4(%rax) */ if (findls(l, 0)) return; /* Matched 4(,%rax,8) */ if (l->n_op == PLUS && isreg(l->n_right)) { if (findls(l->n_left, 0)) return; /* Matched 4(%rbx,%rax,8) */ (void)geninsn(l->n_left, INAREG); return; /* Generate 4(%rbx,%rax) */ } (void)geninsn(l, INAREG); return; /* Generate 4(%rbx) */ } if (p->n_op == PLUS) { if (!isreg(p->n_left)) /* ensure right is REG */ (void)geninsn(p->n_left, INAREG); if (isreg(p->n_right)) return; /* Matched (%rax,%rbx) */ if (findls(p->n_right, 0)) return; /* Matched (%rax,%rbx,4) */ (void)geninsn(p->n_right, INAREG); return; /* Generate (%rbx,%rax) */ } (void)geninsn(p, INAREG); }
void offstar(NODE *p, int shape) { NODE *q; if (x2debug) printf("offstar(%p)\n", p); if( p->n_op == PLUS || p->n_op == MINUS ){ if( p->n_right->n_op == ICON ){ q = p->n_left; if (q->n_op != REG) geninsn(q, INAREG); p->n_su = -1; } } geninsn(p, INAREG); }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. */ void offstar(NODE *p, int shape) { NODE *r; if (x2debug) printf("offstar(%p)\n", p); if (isreg(p)) return; /* Is already OREG */ r = p->n_right; if( p->n_op == PLUS || p->n_op == MINUS ){ if( r->n_op == ICON ){ if (isreg(p->n_left) == 0 || (p->n_left->n_op == REG && p->n_left->n_rval != 2 && p->n_left->n_rval != 3)) (void)geninsn(p->n_left, INBREG); /* Converted in ormake() */ return; } } (void)geninsn(p, INBREG); }
/* * Check if LS and try to make it indexable. * Ignore SCONV to long. * Return 0 if failed. */ static int findls(NODE *p, int check) { CONSZ c; if (p->n_op == SCONV && p->n_type == LONG && p->n_left->n_type == INT) p = p->n_left; /* Ignore pointless SCONVs here */ if (p->n_op != LS || p->n_right->n_op != ICON) return 0; if ((c = p->n_right->n_lval) != 1 && c != 2 && c != 3) return 0; if (check == 1 && p->n_left->n_op != REG) return 0; if (!isreg(p->n_left)) (void)geninsn(p->n_left, INAREG); return 1; }