void i_fg_build (void) { unsigned i; i_puint32 cp = i_buf; /* Start of code to analyze */ i_puint32 lp = i_lim; /* End of code to analyze */ i_uint32 op; /* Current opcode */ i_bb_t b; /* Current basic block */ num_bb = 0; b = bb_alloc(); b->h = cp; if (i_ralloctype == RA_EZ) { i_fg_root = i_fg_tail = b; b->t = lp - i_isize; return; } i_calls_cur = i_calls_lim = 0; NEW0(lbl2bb, i_lab_cur); NEW(fwdrefs, i_nbb); fwdref_cur = 0; i_fg_root = b; do { assert(b && !b->init); op = get_op(cp); switch(i_op2class[op]) { case I_BOP: case I_BOPF: case I_MOPR: case I_MOPRF: assert(!isimmed(op)); markuse(b, get_rs(cp)); markuse(b, get_rs2(cp)); markdef(b, get_rd(cp)); break; case I_BOPI: case I_MOPRI: case I_MOPRIF: assert(isimmed(op)); markuse(b, get_rs(cp)); markdef(b, get_rd(cp)); break; case I_MOPW: case I_MOPWF: assert(!isimmed(op)); markuse(b, get_rd(cp)); markuse(b, get_rs(cp)); markuse(b, get_rs2(cp)); break; case I_MOPWI: case I_MOPWIF: assert(isimmed(op)); markuse(b, get_rd(cp)); markuse(b, get_rs(cp)); break; case I_UOP: case I_UOPF: assert(!isimmed(op)); markuse(b, get_rs(cp)); markdef(b, get_rd(cp)); break; case I_UOPI: assert(isimmed(op)); markdef(b, get_rd(cp)); break; case I_SET: case I_SETF: markdef(b, get_rd(cp)); break; case I_LEA: case I_LEAF: SCLASS(get_rs(cp)) = STACK; markuse(b, get_rs(cp)); markdef(b, get_rd(cp)); break; case I_RET: case I_RETF: if (op != i_op_retv) markuse(b, get_rd(cp)); case I_RETI: b = bb_finalize(b, cp, lp, i_isize, false); break; case I_BR: case I_BRF: markuse(b, get_rs2(cp)); case I_BRI: markuse(b, get_rs(cp)); bb_linklbl(b, get_rd(cp)); b = bb_finalize(b, cp, lp, i_isize, true); break; case I_CALL: case I_CALLF: markuse(b, get_rs(cp)); case I_CALLI: case I_CALLIF: if (op != i_op_callv && op != i_op_callvi) markdef(b, get_rd(cp)); markcall(cp); b = bb_finalize(b, cp, lp, 2*i_isize, true); cp += i_isize; /* Calls are 2x as long as other insns */ break; case I_ARG: case I_ARGF: markuse(b, get_rd(cp)); break; case I_JMP: assert(get_rd(cp) < num_i); markuse(b, get_rd(cp)); b = bb_finalize(b, cp, lp, i_isize, false); break; case I_JMPI: bb_linklbl(b, get_imm(cp)); b = bb_finalize(b, cp, lp, i_isize, false); break; case I_MISC: switch (op) { case i_op_lbl: if (cp > b->h) /* If not at head of current block ... */ /* ... make this the head of a new block */ b = bb_finalize(b, cp-i_isize, lp, i_isize, true); lbl2bb[get_rd(cp)] = b; break; default: /* refmul, refdiv, self, nop */ break; } break; default: assert(0); } } while ((cp += i_isize) < lp); i_fg_tail = b; for (i = 0; i < fwdref_cur; i++) bb_linkbb(fwdrefs[i].src, lbl2bb[fwdrefs[i].dst]); #ifndef NDEBUG for (i = 0, b = i_fg_root; b; b = b->lnext) i++; assert(i == num_bb); #endif }
static int match_type(InstFmt i, struct riscv_op *op, vm_offset_t loc) { uint32_t val; int found; int imm; val = 0; imm = get_imm(i, op->type, &val); if (strcmp(op->type, "U") == 0) { oprint(op, loc, i.UType.rd, 0, 0, val, imm); return (1); } if (strcmp(op->type, "UJ") == 0) { oprint(op, loc, 0, 0, 0, val, (loc + imm)); return (1); } if ((strcmp(op->type, "I") == 0) && \ (op->funct3 == i.IType.funct3)) { found = 0; if (op->funct7 != -1) { if (op->funct7 == i.IType.imm) found = 1; } else found = 1; if (found) { oprint(op, loc, i.IType.rd, i.IType.rs1, 0, val, imm); return (1); } } if ((strcmp(op->type, "S") == 0) && \ (op->funct3 == i.SType.funct3)) { oprint(op, loc, 0, i.SType.rs1, i.SType.rs2, val, imm); return (1); } if ((strcmp(op->type, "SB") == 0) && \ (op->funct3 == i.SBType.funct3)) { oprint(op, loc, 0, i.SBType.rs1, i.SBType.rs2, val, imm); return (1); } if ((strcmp(op->type, "R2") == 0) && \ (op->funct3 == i.R2Type.funct3) && \ (op->funct7 == i.R2Type.funct7)) { oprint(op, loc, i.R2Type.rd, i.R2Type.rs1, i.R2Type.rs2, val, imm); return (1); } if ((strcmp(op->type, "R") == 0) && \ (op->funct3 == i.RType.funct3) && \ (op->funct7 == i.RType.funct7)) { oprint(op, loc, i.RType.rd, i.RType.rs1, val, i.RType.rs2, imm); return (1); } return (0); }