Exemplo n.º 1
0
void alu_unit(int s, int t) {
    struct ins* i = CPU.pipeline[1];
    int opc = i->opcode;
    short c = i->c;
    if(opc) {

        if(opc == _addi) addi(s, c);
        else if(opc == _halt) printf("encounter halt\n");
        else if(is_load(opc) || is_store(opc)) load_store(s, c);
        else if(opc == _lui) lui(c); 
        else if(opc == _andi) andi(s, c);
        else if(opc == _ori) ori(s, c);
        else if(opc == _nori) nori(s, c);
        else if(opc == _slti) slti(s, c);

    } else {
        int func = i->func;
        int shamt = i->shamt;
        
        if(func == _add) add(0, s, t);
        else if(func == _sub) add(1, s, t);
        else if(func == _and) and(0, s, t);
        else if(func == _or) or(0, s, t);
        else if(func == _xor) or(1, s, t);
        else if(func == _nor) or(2, s, t);
        else if(func == _nand) and(1, s, t);
        else if(func == _slt) slt(s, t);
        else if(func == _sll) sll(t, shamt);
        else if(func == _srl) sr(0, t, shamt);
        else if(func == _sra) sr(1, t, shamt);
    }
}
static bool valid_flags(struct ir3_instruction *instr, unsigned n,
		unsigned flags)
{
	unsigned valid_flags;
	flags = cp_flags(flags);

	/* If destination is indirect, then source cannot be.. at least
	 * I don't think so..
	 */
	if ((instr->regs[0]->flags & IR3_REG_RELATIV) &&
			(flags & IR3_REG_RELATIV))
		return false;

	/* TODO it seems to *mostly* work to cp RELATIV, except we get some
	 * intermittent piglit variable-indexing fails.  Newer blob driver
	 * doesn't seem to cp these.  Possibly this is hw workaround?  Not
	 * sure, but until that is understood better, lets just switch off
	 * cp for indirect src's:
	 */
	if (flags & IR3_REG_RELATIV)
		return false;

	switch (opc_cat(instr->opc)) {
	case 1:
		valid_flags = IR3_REG_IMMED | IR3_REG_CONST | IR3_REG_RELATIV;
		if (flags & ~valid_flags)
			return false;
		break;
	case 2:
		valid_flags = ir3_cat2_absneg(instr->opc) |
				IR3_REG_CONST | IR3_REG_RELATIV;

		if (ir3_cat2_int(instr->opc))
			valid_flags |= IR3_REG_IMMED;

		if (flags & ~valid_flags)
			return false;

		if (flags & (IR3_REG_CONST | IR3_REG_IMMED)) {
			unsigned m = (n ^ 1) + 1;
			/* cannot deal w/ const in both srcs:
			 * (note that some cat2 actually only have a single src)
			 */
			if (m < instr->regs_count) {
				struct ir3_register *reg = instr->regs[m];
				if ((flags & IR3_REG_CONST) && (reg->flags & IR3_REG_CONST))
					return false;
				if ((flags & IR3_REG_IMMED) && (reg->flags & IR3_REG_IMMED))
					return false;
			}
			/* cannot be const + ABS|NEG: */
			if (flags & (IR3_REG_FABS | IR3_REG_FNEG |
					IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))
				return false;
		}
		break;
	case 3:
		valid_flags = ir3_cat3_absneg(instr->opc) |
				IR3_REG_CONST | IR3_REG_RELATIV;

		if (flags & ~valid_flags)
			return false;

		if (flags & (IR3_REG_CONST | IR3_REG_RELATIV)) {
			/* cannot deal w/ const/relativ in 2nd src: */
			if (n == 1)
				return false;
		}

		if (flags & IR3_REG_CONST) {
			/* cannot be const + ABS|NEG: */
			if (flags & (IR3_REG_FABS | IR3_REG_FNEG |
					IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))
				return false;
		}
		break;
	case 4:
		/* seems like blob compiler avoids const as src.. */
		/* TODO double check if this is still the case on a4xx */
		if (flags & (IR3_REG_CONST | IR3_REG_IMMED))
			return false;
		if (flags & (IR3_REG_SABS | IR3_REG_SNEG))
			return false;
		break;
	case 5:
		/* no flags allowed */
		if (flags)
			return false;
		break;
	case 6:
		valid_flags = IR3_REG_IMMED;
		if (flags & ~valid_flags)
			return false;

		if (flags & IR3_REG_IMMED) {
			/* doesn't seem like we can have immediate src for store
			 * instructions:
			 *
			 * TODO this restriction could also apply to load instructions,
			 * but for load instructions this arg is the address (and not
			 * really sure any good way to test a hard-coded immed addr src)
			 */
			if (is_store(instr) && (n == 1))
				return false;

			/* disallow CP into anything but the SSBO slot argument for
			 * atomics:
			 */
			if (is_atomic(instr->opc) && (n != 0))
				return false;
		}

		break;
	}

	return true;
}