Exemplo n.º 1
0
void fn_lcd(char **args)
{
	char *lwd, *exp;
	int freep;

	if (args) {
	    lwd = args[0];
	    freep = 0;
	}
	else {
	    if (rc_inrc) {
		rc_error("lcd: no directory specified");
		return;
	    }
	    lwd = read_string("local directory: ", 1);
	    freep = 1;
	}
	exp = local_exp(lwd);
	if (exp) {
	    if (chdir(exp) < 0 && rc_inrc)
		rc_error("rc: cannot cd to %s: %s",
			 lwd, strerror(errno));
	    free(exp);
	}
	if (freep)
	    free(lwd);

	if (!rc_inrc) {
	    lwd = getcwd(NULL, 1024);
	    disp_status(DISP_STATUS, "Current local directory: %s", lwd);
	    free(lwd);
	}
}
Exemplo n.º 2
0
Arquivo: glom.c Projeto: muennich/rc3
extern void assign(List *s1, List *s2, bool stack) {
	List *val = s2;
	if (s1 == NULL)
		rc_error("null variable name");
	if (s1->n != NULL)
		rc_error("multi-word variable name");
	if (*s1->w == '\0')
		rc_error("zero-length variable name");
	if (a2u(s1->w) != -1)
		rc_error("numeric variable name");
	if (strchr(s1->w, '=') != NULL)
		rc_error("'=' in variable name");
	if (*s1->w == '*' && s1->w[1] == '\0')
		val = append(varlookup("0"), s2); /* preserve $0 when * is assigned explicitly */
	if (s2 != NULL || stack) {
		if (dashex)
			prettyprint_var(2, s1->w, val);
		varassign(s1->w, val, stack);
		alias(s1->w, varlookup(s1->w), stack);
	} else {
		if (dashex)
			prettyprint_var(2, s1->w, NULL);
		varrm(s1->w, stack);
	}
}
Exemplo n.º 3
0
static void ei_if(struct r300_vertex_program_compiler * compiler,
					struct rc_instruction *rci,
					unsigned int * inst,
					unsigned int branch_depth)
{
	unsigned int predicate_opcode;
	int is_math = 0;

	if (!compiler->Base.is_r500) {
		rc_error(&compiler->Base,"Opcode IF not supported\n");
		return;
	}

	/* Reserve a temporary to use as our predicate stack counter, if we
	 * don't already have one. */
	if (!compiler->PredicateMask) {
		unsigned int writemasks[RC_REGISTER_MAX_INDEX];
		struct rc_instruction * inst;
		unsigned int i;
		memset(writemasks, 0, sizeof(writemasks));
		for(inst = compiler->Base.Program.Instructions.Next;
				inst != &compiler->Base.Program.Instructions;
							inst = inst->Next) {
			rc_for_all_writes_mask(inst, mark_write, writemasks);
		}
		for(i = 0; i < compiler->Base.max_temp_regs; i++) {
			unsigned int mask = ~writemasks[i] & RC_MASK_XYZW;
			/* Only the W component can be used fo the predicate
			 * stack counter. */
			if (mask & RC_MASK_W) {
				compiler->PredicateMask = RC_MASK_W;
				compiler->PredicateIndex = i;
				break;
			}
		}
		if (i == compiler->Base.max_temp_regs) {
			rc_error(&compiler->Base, "No free temporary to use for"
					" predicate stack counter.\n");
			return;
		}
	}
	predicate_opcode =
			branch_depth ? VE_PRED_SET_NEQ_PUSH : ME_PRED_SET_NEQ;

	rci->U.I.SrcReg[0].Swizzle = RC_MAKE_SWIZZLE_SMEAR(GET_SWZ(rci->U.I.SrcReg[0].Swizzle,0));
	if (branch_depth == 0) {
		is_math = 1;
		predicate_opcode = ME_PRED_SET_NEQ;
		inst[1] = t_src(compiler->code, &rci->U.I.SrcReg[0]);
		inst[2] = 0;
	} else {
		predicate_opcode = VE_PRED_SET_NEQ_PUSH;
		inst[1] = t_pred_src(compiler);
		inst[2] = t_src(compiler->code, &rci->U.I.SrcReg[0]);
	}

	inst[0] = t_pred_dst(compiler, predicate_opcode, is_math);
	inst[3] = 0;

}
Exemplo n.º 4
0
void r500BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
{
	struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c;
	struct emit_state s;
	struct r500_fragment_program_code *code = &compiler->code->code.r500;

	memset(&s, 0, sizeof(s));
	s.C = &compiler->Base;
	s.Code = code;

	memset(code, 0, sizeof(*code));
	code->max_temp_idx = 1;
	code->inst_end = -1;

	for(struct rc_instruction * inst = compiler->Base.Program.Instructions.Next;
	    inst != &compiler->Base.Program.Instructions && !compiler->Base.Error;
	    inst = inst->Next) {
		if (inst->Type == RC_INSTRUCTION_NORMAL) {
			const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);

			if (opcode->IsFlowControl) {
				emit_flowcontrol(&s, inst);
			} else if (inst->U.I.Opcode == RC_OPCODE_BEGIN_TEX) {
				continue;
			} else {
				emit_tex(compiler, &inst->U.I);
			}
		} else {
			emit_paired(compiler, &inst->U.P);
		}
	}

	if (code->max_temp_idx >= compiler->Base.max_temp_regs)
		rc_error(&compiler->Base, "Too many hardware temporaries used");

	if (compiler->Base.Error)
		return;

	if (code->inst_end == -1 ||
	    (code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) {
		/* This may happen when dead-code elimination is disabled or
		 * when most of the fragment program logic is leading to a KIL */
		if (code->inst_end >= compiler->Base.max_alu_insts-1) {
			rc_error(&compiler->Base, "Introducing fake OUT: Too many instructions");
			return;
		}

		int ip = ++code->inst_end;
		code->inst[ip].inst0 = R500_INST_TYPE_OUT | R500_INST_TEX_SEM_WAIT;
	}

	/* Enable full flow control mode if we are using loops or have if
	 * statements nested at least four deep. */
	if (s.MaxBranchDepth >= 4 || s.LoopsReserved > 0) {
		if (code->max_temp_idx < 1)
			code->max_temp_idx = 1;

		code->us_fc_ctrl |= R500_FC_FULL_FC_EN;
	}
}
Exemplo n.º 5
0
static void translate_vertex_program(struct r300_vertex_program_compiler * compiler)
{
	struct rc_instruction *rci;

	compiler->code->pos_end = 0;	/* Not supported yet */
	compiler->code->length = 0;

	compiler->SetHwInputOutput(compiler);

	for(rci = compiler->Base.Program.Instructions.Next; rci != &compiler->Base.Program.Instructions; rci = rci->Next) {
		struct rc_sub_instruction *vpi = &rci->U.I;
		unsigned int *inst = compiler->code->body.d + compiler->code->length;

		/* Skip instructions writing to non-existing destination */
		if (!valid_dst(compiler->code, &vpi->DstReg))
			continue;

		if (compiler->code->length >= VSF_MAX_FRAGMENT_LENGTH) {
			rc_error(&compiler->Base, "Vertex program has too many instructions\n");
			return;
		}

		switch (vpi->Opcode) {
		case RC_OPCODE_ADD: ei_vector2(compiler->code, VE_ADD, vpi, inst); break;
		case RC_OPCODE_ARL: ei_vector1(compiler->code, VE_FLT2FIX_DX, vpi, inst); break;
		case RC_OPCODE_DP4: ei_vector2(compiler->code, VE_DOT_PRODUCT, vpi, inst); break;
		case RC_OPCODE_DST: ei_vector2(compiler->code, VE_DISTANCE_VECTOR, vpi, inst); break;
		case RC_OPCODE_EX2: ei_math1(compiler->code, ME_EXP_BASE2_FULL_DX, vpi, inst); break;
		case RC_OPCODE_EXP: ei_math1(compiler->code, ME_EXP_BASE2_DX, vpi, inst); break;
		case RC_OPCODE_FRC: ei_vector1(compiler->code, VE_FRACTION, vpi, inst); break;
		case RC_OPCODE_LG2: ei_math1(compiler->code, ME_LOG_BASE2_FULL_DX, vpi, inst); break;
		case RC_OPCODE_LIT: ei_lit(compiler->code, vpi, inst); break;
		case RC_OPCODE_LOG: ei_math1(compiler->code, ME_LOG_BASE2_DX, vpi, inst); break;
		case RC_OPCODE_MAD: ei_mad(compiler->code, vpi, inst); break;
		case RC_OPCODE_MAX: ei_vector2(compiler->code, VE_MAXIMUM, vpi, inst); break;
		case RC_OPCODE_MIN: ei_vector2(compiler->code, VE_MINIMUM, vpi, inst); break;
		case RC_OPCODE_MOV: ei_vector1(compiler->code, VE_ADD, vpi, inst); break;
		case RC_OPCODE_MUL: ei_vector2(compiler->code, VE_MULTIPLY, vpi, inst); break;
		case RC_OPCODE_POW: ei_pow(compiler->code, vpi, inst); break;
		case RC_OPCODE_RCP: ei_math1(compiler->code, ME_RECIP_DX, vpi, inst); break;
		case RC_OPCODE_RSQ: ei_math1(compiler->code, ME_RECIP_SQRT_DX, vpi, inst); break;
		case RC_OPCODE_SGE: ei_vector2(compiler->code, VE_SET_GREATER_THAN_EQUAL, vpi, inst); break;
		case RC_OPCODE_SLT: ei_vector2(compiler->code, VE_SET_LESS_THAN, vpi, inst); break;
		default:
			rc_error(&compiler->Base, "Unknown opcode %i\n", vpi->Opcode);
			return;
		}

		compiler->code->length += 4;

		if (compiler->Base.Error)
			return;
	}
}
Exemplo n.º 6
0
static void dopipe(Node *n) {
	int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2];
	bool intr;
	Node *r;

	fd_prev = fd_out = 1;
	for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) {
		if (i > 500) /* the only hard-wired limit in rc? */
			rc_error("pipe too long");
		if (pipe(p) < 0) {
			uerror("pipe");
			rc_error(NULL);
		}
		if ((pid = rc_fork()) == 0) {
			setsigdefaults(FALSE);
			redirq = NULL; /* clear preredir queue */
			mvfd(p[0], r->u[1].i);
			if (fd_prev != 1)
				mvfd(fd_prev, fd_out);
			close(p[1]);
			walk(r->u[3].p, FALSE);
			exit(getstatus());
		}
		if (fd_prev != 1)
			close(fd_prev); /* parent must close all pipe fd's */
		pids[i] = pid;
		fd_prev = p[1];
		fd_out = r->u[0].i;
		close(p[0]);
	}
	if ((pid = rc_fork()) == 0) {
		setsigdefaults(FALSE);
		mvfd(fd_prev, fd_out);
		walk(r, FALSE);
		exit(getstatus());
		/* NOTREACHED */
	}
	redirq = NULL; /* clear preredir queue */
	close(fd_prev);
	pids[i++] = pid;

	/* collect statuses */

	intr = FALSE;
	for (j = 0; j < i; j++) {
		rc_wait4(pids[j], &sp, TRUE);
		stats[j] = sp;
		intr |= (sp == SIGINT);
	}
	setpipestatus(stats, i);
	sigchk();
}
/**
 * This function prepares a loop to be unrolled by converting it into an if
 * statement.  Here is an outline of the conversion process:
 * BGNLOOP;                         	-> BGNLOOP;
 * <Additional conditional code>	-> <Additional conditional code>
 * SGE/SLT temp[0], temp[1], temp[2];	-> SLT/SGE temp[0], temp[1], temp[2];
 * IF temp[0];                      	-> IF temp[0];
 * BRK;                             	->
 * ENDIF;                           	-> <Loop Body>
 * <Loop Body>                      	-> ENDIF;
 * ENDLOOP;                         	-> ENDLOOP
 *
 * @param inst A pointer to a BGNLOOP instruction.
 * @return 1 for success, 0 for failure
 */
static int transform_loop(struct emulate_loop_state * s,
						struct rc_instruction * inst)
{
	struct loop_info * loop;

	memory_pool_array_reserve(&s->C->Pool, struct loop_info,
			s->Loops, s->LoopCount, s->LoopReserved, 1);

	loop = &s->Loops[s->LoopCount++];

	if (!build_loop_info(s->C, loop, inst)) {
		rc_error(s->C, "Failed to build loop info\n");
		return 0;
	}

	if(try_unroll_loop(s->C, loop)){
		return 1;
	}

	/* Reverse the conditional instruction */
	switch(loop->Cond->U.I.Opcode){
	case RC_OPCODE_SGE:
		loop->Cond->U.I.Opcode = RC_OPCODE_SLT;
		break;
	case RC_OPCODE_SLT:
		loop->Cond->U.I.Opcode = RC_OPCODE_SGE;
		break;
	case RC_OPCODE_SLE:
		loop->Cond->U.I.Opcode = RC_OPCODE_SGT;
		break;
	case RC_OPCODE_SGT:
		loop->Cond->U.I.Opcode = RC_OPCODE_SLE;
		break;
	case RC_OPCODE_SEQ:
		loop->Cond->U.I.Opcode = RC_OPCODE_SNE;
		break;
	case RC_OPCODE_SNE:
		loop->Cond->U.I.Opcode = RC_OPCODE_SEQ;
		break;
	default:
		rc_error(s->C, "loop->Cond is not a conditional.\n");
		return 0;
	}

	/* Prepare the loop to be emulated */
	rc_remove_instruction(loop->Brk);
	rc_remove_instruction(loop->EndIf);
	rc_insert_instruction(loop->EndLoop->Prev, loop->EndIf);
	return 1;
}
Exemplo n.º 8
0
static void scan_write(void * data, struct rc_instruction * inst,
		rc_register_file file, unsigned int index, unsigned int chan)
{
	struct schedule_state * s = data;
	struct reg_value ** pv = get_reg_valuep(s, file, index, chan);

	if (!pv)
		return;

	DBG("%i: write %i[%i] chan %i\n", s->Current->Instruction->IP, file, index, chan);

	struct reg_value * newv = memory_pool_malloc(&s->C->Pool, sizeof(*newv));
	memset(newv, 0, sizeof(*newv));

	newv->Writer = s->Current;

	if (*pv) {
		(*pv)->Next = newv;
		s->Current->NumDependencies++;
	}

	*pv = newv;

	if (s->Current->NumWriteValues >= 4) {
		rc_error(s->C, "%s: NumWriteValues overflow\n", __FUNCTION__);
	} else {
		s->Current->WriteValues[s->Current->NumWriteValues++] = newv;
	}
}
static void do_regalloc(struct regalloc_state * s)
{
	/* Simple and stupid greedy register allocation */
	for(unsigned int index = 0; index < RC_REGISTER_MAX_INDEX; ++index) {
		struct register_info * reg = &s->Temporary[index];

		if (!reg->Used)
			continue;

		for(unsigned int hwreg = 0; hwreg < s->NumHwTemporaries; ++hwreg) {
			if (try_add_live_intervals(s, &s->HwTemporary[hwreg].Used, &reg->Live)) {
				reg->Allocated = 1;
				reg->File = RC_FILE_TEMPORARY;
				reg->Index = hwreg;
				goto success;
			}
		}

		rc_error(s->C, "Ran out of hardware temporaries\n");
		return;

	success:;
	}

	/* Rewrite all instructions based on the translation table we built */
	for(struct rc_instruction * inst = s->C->Program.Instructions.Next;
	    inst != &s->C->Program.Instructions;
	    inst = inst->Next) {
		if (inst->Type == RC_INSTRUCTION_NORMAL)
			rewrite_normal_instruction(s, &inst->U.I);
		else
			rewrite_pair_instruction(s, &inst->U.P);
	}
}
Exemplo n.º 10
0
Arquivo: glom.c Projeto: muennich/rc3
static List *backq(Node *ifs, Node *n) {
	int p[2], sp;
	pid_t pid;
	List *bq;
	struct termios t;
	if (n == NULL)
		return NULL;
	if (pipe(p) < 0) {
		uerror("pipe");
		rc_error(NULL);
	}
	if (interactive)
		tcgetattr(0, &t);
	if ((pid = rc_fork()) == 0) {
		mvfd(p[1], 1);
		close(p[0]);
		redirq = NULL;
		walk(n, FALSE);
		exit(getstatus());
	}
	close(p[1]);
	bq = bqinput(glom(ifs), p[0]);
	close(p[0]);
	rc_wait4(pid, &sp, TRUE);
	if (interactive && WIFSIGNALED(sp))
		tcsetattr(0, TCSANOW, &t);
	statprint(-1, sp);
	varassign("bqstatus", word(strstatus(sp), NULL), FALSE);
	sigchk();
	return bq;
}
Exemplo n.º 11
0
void rc_validate_final_shader(struct radeon_compiler *c, void *user)
{
	/* Check the number of constants. */
	if (c->Program.Constants.Count > c->max_constants) {
		rc_error(c, "Too many constants. Max: 256, Got: %i\n",
			 c->Program.Constants.Count);
	}
}
Exemplo n.º 12
0
static void ei_endif(struct r300_vertex_program_compiler *compiler,
							unsigned int * inst)
{
	if (!compiler->Base.is_r500) {
		rc_error(&compiler->Base,"Opcode ENDIF not supported\n");
		return;
	}
	inst[0] = t_pred_dst(compiler, ME_PRED_SET_POP, 1);
	inst[1] = t_pred_src(compiler);
	inst[2] = 0;
	inst[3] = 0;
}
Exemplo n.º 13
0
static uint32_t translate_alu_result_op(struct r300_fragment_program_compiler * c, rc_compare_func func)
{
	switch(func) {
	case RC_COMPARE_FUNC_EQUAL: return R500_INST_ALU_RESULT_OP_EQ;
	case RC_COMPARE_FUNC_LESS: return R500_INST_ALU_RESULT_OP_LT;
	case RC_COMPARE_FUNC_GEQUAL: return R500_INST_ALU_RESULT_OP_GE;
	case RC_COMPARE_FUNC_NOTEQUAL: return R500_INST_ALU_RESULT_OP_NE;
	default:
		rc_error(&c->Base, "%s: unsupported compare func %i\n", __FUNCTION__, func);
		return 0;
	}
}
Exemplo n.º 14
0
extern void rc_raise(ecodes e) {
	if (e == eError && rc_pid != getpid())
		exit(1); /* child processes exit on an error/signal */
	for (; estack != NULL; estack = estack->prev)
		if (estack->e != e) {
			if (e == eBreak && estack->e != eArena && estack->e != eVarstack)
				rc_error("break outside of loop");
			else if (e == eReturn && estack->e == eError) /* can return from loops inside functions */
				rc_error("return outside of function");
			switch (estack->e) {
			default:
				break;
			case eVarstack:
				varrm(estack->data.name, TRUE);
				break;
			case eArena:
				restoreblock(estack->data.b);
				break;
			case eFifo:
				unlink(estack->data.name);
				break;
			case eFd:
				close(estack->data.fd);
				break;
			}
		} else {
			if (e == eError && !estack->interactive) {
				popinput();
			} else {
				Jbwrap *j = estack->data.jb;

				interactive = estack->interactive;
				estack = estack->prev;
				siglongjmp(j->j, 1);
			}
		}
	rc_exit(1); /* top of exception stack */
}
Exemplo n.º 15
0
static float get_constant_value(struct radeon_compiler * c,
						struct rc_src_register * src,
						int chan)
{
	float base = 1.0f;
	int swz = GET_SWZ(src->Swizzle, chan);
	if(swz >= 4 || src->Index >= c->Program.Constants.Count ){
		rc_error(c, "get_constant_value: Can't find a value.\n");
		return 0.0f;
	}
	if(GET_BIT(src->Negate, chan)){
		base = -1.0f;
	}
	return base *
		c->Program.Constants.Constants[src->Index].u.Immediate[swz];
}
Exemplo n.º 16
0
/**
 * This function renames registers in an attempt to get the code close to
 * SSA form.  After this function has completed, most of the register are only
 * written to one time, with a few exceptions.
 *
 * This function assumes all the instructions are still of type
 * RC_INSTRUCTION_NORMAL.
 */
void rc_rename_regs(struct radeon_compiler *c, void *user)
{
	unsigned int i, used_length;
	int new_index;
	struct rc_instruction * inst;
	struct rc_reader_data reader_data;
	unsigned char * used;

	/* XXX Remove this once the register allocation works with flow control. */
	for(inst = c->Program.Instructions.Next;
					inst != &c->Program.Instructions;
					inst = inst->Next) {
		if (inst->U.I.Opcode == RC_OPCODE_BGNLOOP)
			return;
	}

	used_length = 2 * rc_recompute_ips(c);
	used = memory_pool_malloc(&c->Pool, sizeof(unsigned char) * used_length);
	memset(used, 0, sizeof(unsigned char) * used_length);

	rc_get_used_temporaries(c, used, used_length);
	for(inst = c->Program.Instructions.Next;
					inst != &c->Program.Instructions;
					inst = inst->Next) {

		if (inst->U.I.DstReg.File != RC_FILE_TEMPORARY)
			continue;

		reader_data.ExitOnAbort = 1;
		rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL);

		if (reader_data.Abort || reader_data.ReaderCount == 0)
			continue;

		new_index = rc_find_free_temporary_list(c, used, used_length,
						RC_MASK_XYZW);
		if (new_index < 0) {
			rc_error(c, "Ran out of temporary registers\n");
			return;
		}

		reader_data.Writer->U.I.DstReg.Index = new_index;
		for(i = 0; i < reader_data.ReaderCount; i++) {
			reader_data.Readers[i].U.I.Src->Index = new_index;
		}
	}
}
Exemplo n.º 17
0
unsigned int rc_find_free_temporary(struct radeon_compiler * c)
{
	unsigned char used[RC_REGISTER_MAX_INDEX];
	int free;

	memset(used, 0, sizeof(used));

	rc_get_used_temporaries(c, used, RC_REGISTER_MAX_INDEX);

	free = rc_find_free_temporary_list(c, used, RC_REGISTER_MAX_INDEX,
								RC_MASK_XYZW);
	if (free < 0) {
		rc_error(c, "Ran out of temporary registers\n");
		return 0;
	}
	return free;
}
Exemplo n.º 18
0
static void scan_read(void * data, struct rc_instruction * inst,
		rc_register_file file, unsigned int index, unsigned int chan)
{
	struct schedule_state * s = data;
	struct reg_value ** v = get_reg_valuep(s, file, index, chan);
	struct reg_value_reader * reader;

	if (!v)
		return;

	if (*v && (*v)->Writer == s->Current) {
		/* The instruction reads and writes to a register component.
		 * In this case, we only want to increment dependencies by one.
		 */
		return;
	}

	DBG("%i: read %i[%i] chan %i\n", s->Current->Instruction->IP, file, index, chan);

	reader = memory_pool_malloc(&s->C->Pool, sizeof(*reader));
	reader->Reader = s->Current;
	if (!*v) {
		/* In this situation, the instruction reads from a register
		 * that hasn't been written to or read from in the current
		 * block. */
		*v = memory_pool_malloc(&s->C->Pool, sizeof(struct reg_value));
		memset(*v, 0, sizeof(struct reg_value));
		(*v)->Readers = reader;
	} else {
		reader->Next = (*v)->Readers;
		(*v)->Readers = reader;
		/* Only update the current instruction's dependencies if the
		 * register it reads from has been written to in this block. */
		if ((*v)->Writer) {
			s->Current->NumDependencies++;
		}
	}
	(*v)->NumReaders++;

	if (s->Current->NumReadValues >= 12) {
		rc_error(s->C, "%s: NumReadValues overflow\n", __FUNCTION__);
	} else {
		s->Current->ReadValues[s->Current->NumReadValues++] = *v;
	}
}
Exemplo n.º 19
0
Arquivo: glom.c Projeto: muennich/rc3
extern List *concat(List *s1, List *s2) {
	int n1, n2;
	List *r, *top;
	if (s1 == NULL)
		return s2;
	if (s2 == NULL)
		return s1;
	if ((n1 = listnel(s1)) != (n2 = listnel(s2)) && n1 != 1 && n2 != 1)
		rc_error("bad concatenation");
	for (r = top = nnew(List); 1; r = r->n = nnew(List)) {
		size_t x = strlen(s1->w);
		size_t y = strlen(s2->w);
		size_t z = x + y + 1;
		r->w = nalloc(z);
		strcpy(r->w, s1->w);
		strcat(r->w, s2->w);
		if (s1->m == NULL && s2->m == NULL) {
			r->m = NULL;
		} else {
			r->m = nalloc(z);
			if (s1->m == NULL)
				memzero(r->m, x);
			else
				memcpy(r->m, s1->m, x);
			if (s2->m == NULL)
				memzero(&r->m[x], y);
			else
				memcpy(&r->m[x], s2->m, y);
			r->m[z] = 0;
		}
		if (n1 > 1)
			s1 = s1->n;
		if (n2 > 1)
			s2 = s2->n;
		if (s1 == NULL || s2 == NULL || (n1 == 1 && n2 == 1))
			break;
	}
	r->n = NULL;
	return top;
}
Exemplo n.º 20
0
Arquivo: glom.c Projeto: muennich/rc3
extern List *varsub(List *var, List *subs) {
	List *r, *top;
	int n = listnel(var);
	for (top = r = NULL; subs != NULL; subs = subs->n) {
		int i = a2u(subs->w);
		if (i < 1)
			rc_error("bad subscript");
		if (i <= n) {
			List *sub = var;
			while (--i)
				sub = sub->n; /* loop until sub == var(i) */
			if (top == NULL)
				top = r = nnew(List);
			else
				r = r->n = nnew(List);
			r->w = sub->w;
			r->m = sub->m;
		}
	}
	if (top != NULL)
		r->n = NULL;
	return top;
}
Exemplo n.º 21
0
static void rc_emulate_negative_addressing(struct radeon_compiler *compiler, void *user)
{
	struct r300_vertex_program_compiler * c = (struct r300_vertex_program_compiler*)compiler;
	struct rc_instruction *inst, *lastARL = NULL;
	int min_offset = 0;

	for (inst = c->Base.Program.Instructions.Next; inst != &c->Base.Program.Instructions; inst = inst->Next) {
		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);

		if (inst->U.I.Opcode == RC_OPCODE_ARL) {
			if (lastARL != NULL && min_offset < 0)
				transform_negative_addressing(c, lastARL, inst, min_offset);

			lastARL = inst;
			min_offset = 0;
			continue;
		}

		for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
			if (inst->U.I.SrcReg[i].RelAddr &&
			    inst->U.I.SrcReg[i].Index < 0) {
				/* ARL must precede any indirect addressing. */
				if (lastARL == NULL) {
					rc_error(&c->Base, "Vertex shader: Found relative addressing without ARL.");
					return;
				}

				if (inst->U.I.SrcReg[i].Index < min_offset)
					min_offset = inst->U.I.SrcReg[i].Index;
			}
		}
	}

	if (lastARL != NULL && min_offset < 0)
		transform_negative_addressing(c, lastARL, inst, min_offset);
}
Exemplo n.º 22
0
static void translate_vertex_program(struct radeon_compiler *c, void *user)
{
	struct r300_vertex_program_compiler *compiler = (struct r300_vertex_program_compiler*)c;
	struct rc_instruction *rci;

	unsigned loops[R500_PVS_MAX_LOOP_DEPTH];
	unsigned loop_depth = 0;

	compiler->code->pos_end = 0;	/* Not supported yet */
	compiler->code->length = 0;
	compiler->code->num_temporaries = 0;

	compiler->SetHwInputOutput(compiler);

	for(rci = compiler->Base.Program.Instructions.Next; rci != &compiler->Base.Program.Instructions; rci = rci->Next) {
		struct rc_sub_instruction *vpi = &rci->U.I;
		unsigned int *inst = compiler->code->body.d + compiler->code->length;
		const struct rc_opcode_info *info = rc_get_opcode_info(vpi->Opcode);

		/* Skip instructions writing to non-existing destination */
		if (!valid_dst(compiler->code, &vpi->DstReg))
			continue;

		if (info->HasDstReg) {
			/* Neither is Saturate. */
			if (vpi->SaturateMode != RC_SATURATE_NONE && !c->is_r500) {
				rc_error(&compiler->Base, "Vertex program does not support the Saturate "
					 "modifier (yet).\n");
			}
		}

		if (compiler->code->length >= c->max_alu_insts * 4) {
			rc_error(&compiler->Base, "Vertex program has too many instructions\n");
			return;
		}

		assert(compiler->Base.is_r500 ||
		       (vpi->Opcode != RC_OPCODE_SEQ &&
			vpi->Opcode != RC_OPCODE_SNE));

		switch (vpi->Opcode) {
		case RC_OPCODE_ADD: ei_vector2(compiler->code, VE_ADD, vpi, inst); break;
		case RC_OPCODE_ARL: ei_vector1(compiler->code, VE_FLT2FIX_DX, vpi, inst); break;
		case RC_OPCODE_COS: ei_math1(compiler->code, ME_COS, vpi, inst); break;
		case RC_OPCODE_DP4: ei_vector2(compiler->code, VE_DOT_PRODUCT, vpi, inst); break;
		case RC_OPCODE_DST: ei_vector2(compiler->code, VE_DISTANCE_VECTOR, vpi, inst); break;
		case RC_OPCODE_EX2: ei_math1(compiler->code, ME_EXP_BASE2_FULL_DX, vpi, inst); break;
		case RC_OPCODE_EXP: ei_math1(compiler->code, ME_EXP_BASE2_DX, vpi, inst); break;
		case RC_OPCODE_FRC: ei_vector1(compiler->code, VE_FRACTION, vpi, inst); break;
		case RC_OPCODE_LG2: ei_math1(compiler->code, ME_LOG_BASE2_FULL_DX, vpi, inst); break;
		case RC_OPCODE_LIT: ei_lit(compiler->code, vpi, inst); break;
		case RC_OPCODE_LOG: ei_math1(compiler->code, ME_LOG_BASE2_DX, vpi, inst); break;
		case RC_OPCODE_MAD: ei_mad(compiler->code, vpi, inst); break;
		case RC_OPCODE_MAX: ei_vector2(compiler->code, VE_MAXIMUM, vpi, inst); break;
		case RC_OPCODE_MIN: ei_vector2(compiler->code, VE_MINIMUM, vpi, inst); break;
		case RC_OPCODE_MOV: ei_vector1(compiler->code, VE_ADD, vpi, inst); break;
		case RC_OPCODE_MUL: ei_vector2(compiler->code, VE_MULTIPLY, vpi, inst); break;
		case RC_OPCODE_POW: ei_pow(compiler->code, vpi, inst); break;
		case RC_OPCODE_RCP: ei_math1(compiler->code, ME_RECIP_DX, vpi, inst); break;
		case RC_OPCODE_RSQ: ei_math1(compiler->code, ME_RECIP_SQRT_DX, vpi, inst); break;
		case RC_OPCODE_SEQ: ei_vector2(compiler->code, VE_SET_EQUAL, vpi, inst); break;
		case RC_OPCODE_SGE: ei_vector2(compiler->code, VE_SET_GREATER_THAN_EQUAL, vpi, inst); break;
		case RC_OPCODE_SIN: ei_math1(compiler->code, ME_SIN, vpi, inst); break;
		case RC_OPCODE_SLT: ei_vector2(compiler->code, VE_SET_LESS_THAN, vpi, inst); break;
		case RC_OPCODE_SNE: ei_vector2(compiler->code, VE_SET_NOT_EQUAL, vpi, inst); break;
		case RC_OPCODE_BGNLOOP:
		{
			if ((!compiler->Base.is_r500
				&& loop_depth >= R300_VS_MAX_LOOP_DEPTH)
				|| loop_depth >= R500_PVS_MAX_LOOP_DEPTH) {
				rc_error(&compiler->Base,
						"Loops are nested too deep.");
				return;
			}
			loops[loop_depth++] = ((compiler->code->length)/ 4) + 1;
			break;
		}
		case RC_OPCODE_ENDLOOP:
		{
			unsigned int act_addr;
			unsigned int last_addr;
			unsigned int ret_addr;

			ret_addr = loops[--loop_depth];
			act_addr = ret_addr - 1;
			last_addr = (compiler->code->length / 4) - 1;

			if (loop_depth >= R300_VS_MAX_FC_OPS) {
				rc_error(&compiler->Base,
					"Too many flow control instructions.");
				return;
			}
			if (compiler->Base.is_r500) {
				compiler->code->fc_op_addrs.r500
					[compiler->code->num_fc_ops].lw =
					R500_PVS_FC_ACT_ADRS(act_addr)
					| R500_PVS_FC_LOOP_CNT_JMP_INST(0x00ff)
					;
				compiler->code->fc_op_addrs.r500
					[compiler->code->num_fc_ops].uw =
					R500_PVS_FC_LAST_INST(last_addr)
					| R500_PVS_FC_RTN_INST(ret_addr)
					;
			} else {
				compiler->code->fc_op_addrs.r300
					[compiler->code->num_fc_ops] =
					R300_PVS_FC_ACT_ADRS(act_addr)
					| R300_PVS_FC_LOOP_CNT_JMP_INST(0xff)
					| R300_PVS_FC_LAST_INST(last_addr)
					| R300_PVS_FC_RTN_INST(ret_addr)
					;
			}
			compiler->code->fc_loop_index[compiler->code->num_fc_ops] =
				R300_PVS_FC_LOOP_INIT_VAL(0x0)
				| R300_PVS_FC_LOOP_STEP_VAL(0x1)
				;
			compiler->code->fc_ops |= R300_VAP_PVS_FC_OPC_LOOP(
						compiler->code->num_fc_ops);
			compiler->code->num_fc_ops++;

			break;
		}

		case RC_ME_PRED_SET_CLR:
			ei_math1(compiler->code, ME_PRED_SET_CLR, vpi, inst);
			break;

		case RC_ME_PRED_SET_INV:
			ei_math1(compiler->code, ME_PRED_SET_INV, vpi, inst);
			break;

		case RC_ME_PRED_SET_POP:
			ei_math1(compiler->code, ME_PRED_SET_POP, vpi, inst);
			break;

		case RC_ME_PRED_SET_RESTORE:
			ei_math1(compiler->code, ME_PRED_SET_RESTORE, vpi, inst);
			break;

		case RC_ME_PRED_SEQ:
			ei_math1(compiler->code, ME_PRED_SET_EQ, vpi, inst);
			break;

		case RC_ME_PRED_SNEQ:
			ei_math1(compiler->code, ME_PRED_SET_NEQ, vpi, inst);
			break;

		case RC_VE_PRED_SNEQ_PUSH:
			ei_vector2(compiler->code, VE_PRED_SET_NEQ_PUSH,
								vpi, inst);
			break;

		default:
			rc_error(&compiler->Base, "Unknown opcode %s\n", info->Name);
			return;
		}

		if (vpi->DstReg.Pred != RC_PRED_DISABLED) {
			inst[0] |= (PVS_DST_PRED_ENABLE_MASK
						<< PVS_DST_PRED_ENABLE_SHIFT);
			if (vpi->DstReg.Pred == RC_PRED_SET) {
				inst[0] |= (PVS_DST_PRED_SENSE_MASK
						<< PVS_DST_PRED_SENSE_SHIFT);
			}
		}

		/* Update the number of temporaries. */
		if (info->HasDstReg && vpi->DstReg.File == RC_FILE_TEMPORARY &&
		    vpi->DstReg.Index >= compiler->code->num_temporaries)
			compiler->code->num_temporaries = vpi->DstReg.Index + 1;

		for (unsigned i = 0; i < info->NumSrcRegs; i++)
			if (vpi->SrcReg[i].File == RC_FILE_TEMPORARY &&
			    vpi->SrcReg[i].Index >= compiler->code->num_temporaries)
				compiler->code->num_temporaries = vpi->SrcReg[i].Index + 1;

		if (compiler->code->num_temporaries > compiler->Base.max_temp_regs) {
			rc_error(&compiler->Base, "Too many temporaries.\n");
			return;
		}

		compiler->code->length += 4;

		if (compiler->Base.Error)
			return;
	}
}
Exemplo n.º 23
0
static void emit_flowcontrol(struct emit_state * s, struct rc_instruction * inst)
{
	unsigned int newip;

	if (s->Code->inst_end >= s->C->max_alu_insts-1) {
		rc_error(s->C, "emit_tex: Too many instructions");
		return;
	}

	newip = ++s->Code->inst_end;

	/* Currently all loops use the same integer constant to intialize
	 * the loop variables. */
	if(!s->Code->int_constants[0]) {
		s->Code->int_constants[0] = R500_FC_INT_CONST_KR(0xff);
		s->Code->int_constant_count = 1;
	}
	s->Code->inst[newip].inst0 = R500_INST_TYPE_FC | R500_INST_ALU_WAIT;

	switch(inst->U.I.Opcode){
	struct branch_info * branch;
	struct r500_loop_info * loop;
	case RC_OPCODE_BGNLOOP:
		memory_pool_array_reserve(&s->C->Pool, struct r500_loop_info,
			s->Loops, s->CurrentLoopDepth, s->LoopsReserved, 1);

		loop = &s->Loops[s->CurrentLoopDepth++];
		memset(loop, 0, sizeof(struct r500_loop_info));
		loop->BranchDepth = s->CurrentBranchDepth;
		loop->BgnLoop = newip;

		s->Code->inst[newip].inst2 = R500_FC_OP_LOOP
			| R500_FC_JUMP_FUNC(0x00)
			| R500_FC_IGNORE_UNCOVERED
			;
		break;
	case RC_OPCODE_BRK:
		loop = &s->Loops[s->CurrentLoopDepth - 1];
		memory_pool_array_reserve(&s->C->Pool, int, loop->Brks,
					loop->BrkCount, loop->BrkReserved, 1);

		loop->Brks[loop->BrkCount++] = newip;
		s->Code->inst[newip].inst2 = R500_FC_OP_BREAKLOOP
			| R500_FC_JUMP_FUNC(0xff)
			| R500_FC_B_OP1_DECR
			| R500_FC_B_POP_CNT(
				s->CurrentBranchDepth - loop->BranchDepth)
			| R500_FC_IGNORE_UNCOVERED
			;
		break;

	case RC_OPCODE_CONT:
		loop = &s->Loops[s->CurrentLoopDepth - 1];
		memory_pool_array_reserve(&s->C->Pool, int, loop->Conts,
					loop->ContCount, loop->ContReserved, 1);
		loop->Conts[loop->ContCount++] = newip;
		s->Code->inst[newip].inst2 = R500_FC_OP_CONTINUE
			| R500_FC_JUMP_FUNC(0xff)
			| R500_FC_B_OP1_DECR
			| R500_FC_B_POP_CNT(
				s->CurrentBranchDepth -	loop->BranchDepth)
			| R500_FC_IGNORE_UNCOVERED
			;
		break;

	case RC_OPCODE_ENDLOOP:
	{
		loop = &s->Loops[s->CurrentLoopDepth - 1];
		/* Emit ENDLOOP */
		s->Code->inst[newip].inst2 = R500_FC_OP_ENDLOOP
			| R500_FC_JUMP_FUNC(0xff)
			| R500_FC_JUMP_ANY
			| R500_FC_IGNORE_UNCOVERED
			;
		/* The constant integer at index 0 is used by all loops. */
		s->Code->inst[newip].inst3 = R500_FC_INT_ADDR(0)
			| R500_FC_JUMP_ADDR(loop->BgnLoop + 1)
			;

		/* Set jump address and int constant for BGNLOOP */
		s->Code->inst[loop->BgnLoop].inst3 = R500_FC_INT_ADDR(0)
			| R500_FC_JUMP_ADDR(newip)
			;

		/* Set jump address for the BRK instructions. */
		while(loop->BrkCount--) {
			s->Code->inst[loop->Brks[loop->BrkCount]].inst3 =
						R500_FC_JUMP_ADDR(newip + 1);
		}

		/* Set jump address for CONT instructions. */
		while(loop->ContCount--) {
			s->Code->inst[loop->Conts[loop->ContCount]].inst3 =
						R500_FC_JUMP_ADDR(newip);
		}
		s->CurrentLoopDepth--;
		break;
	}
	case RC_OPCODE_IF:
		if ( s->CurrentBranchDepth >= R500_PFS_MAX_BRANCH_DEPTH_FULL) {
			rc_error(s->C, "Branch depth exceeds hardware limit");
			return;
		}
		memory_pool_array_reserve(&s->C->Pool, struct branch_info,
				s->Branches, s->CurrentBranchDepth, s->BranchesReserved, 1);

		branch = &s->Branches[s->CurrentBranchDepth++];
		branch->If = newip;
		branch->Else = -1;
		branch->Endif = -1;

		if (s->CurrentBranchDepth > s->MaxBranchDepth)
			s->MaxBranchDepth = s->CurrentBranchDepth;

		/* actual instruction is filled in at ENDIF time */
		break;
	
	case RC_OPCODE_ELSE:
		if (!s->CurrentBranchDepth) {
			rc_error(s->C, "%s: got ELSE outside a branch", __FUNCTION__);
			return;
		}

		branch = &s->Branches[s->CurrentBranchDepth - 1];
		branch->Else = newip;

		/* actual instruction is filled in at ENDIF time */
		break;

	case RC_OPCODE_ENDIF:
		if (!s->CurrentBranchDepth) {
			rc_error(s->C, "%s: got ELSE outside a branch", __FUNCTION__);
			return;
		}

		branch = &s->Branches[s->CurrentBranchDepth - 1];
		branch->Endif = newip;

		s->Code->inst[branch->Endif].inst2 = R500_FC_OP_JUMP
			| R500_FC_A_OP_NONE /* no address stack */
			| R500_FC_JUMP_ANY /* docs says set this, but I don't understand why */
			| R500_FC_B_OP0_DECR /* decrement branch counter if stay */
			| R500_FC_B_OP1_NONE /* no branch counter if stay */
			| R500_FC_B_POP_CNT(1)
			;
		s->Code->inst[branch->Endif].inst3 = R500_FC_JUMP_ADDR(branch->Endif + 1);
		s->Code->inst[branch->If].inst2 = R500_FC_OP_JUMP
			| R500_FC_A_OP_NONE /* no address stack */
			| R500_FC_JUMP_FUNC(0x0f) /* jump if ALU result is false */
			| R500_FC_B_OP0_INCR /* increment branch counter if stay */
			| R500_FC_IGNORE_UNCOVERED
		;

		if (branch->Else >= 0) {
			/* increment branch counter also if jump */
			s->Code->inst[branch->If].inst2 |= R500_FC_B_OP1_INCR;
			s->Code->inst[branch->If].inst3 = R500_FC_JUMP_ADDR(branch->Else + 1);

			s->Code->inst[branch->Else].inst2 = R500_FC_OP_JUMP
				| R500_FC_A_OP_NONE /* no address stack */
				| R500_FC_B_ELSE /* all active pixels want to jump */
				| R500_FC_B_OP0_NONE /* no counter op if stay */
				| R500_FC_B_OP1_DECR /* decrement branch counter if jump */
				| R500_FC_B_POP_CNT(1)
			;
			s->Code->inst[branch->Else].inst3 = R500_FC_JUMP_ADDR(branch->Endif + 1);
		} else {
			/* don't touch branch counter on jump */
			s->Code->inst[branch->If].inst2 |= R500_FC_B_OP1_NONE;
			s->Code->inst[branch->If].inst3 = R500_FC_JUMP_ADDR(branch->Endif + 1);
		}


		s->CurrentBranchDepth--;
		break;
	default:
		rc_error(s->C, "%s: unknown opcode %s\n", __FUNCTION__, rc_get_opcode_info(inst->U.I.Opcode)->Name);
	}
}
Exemplo n.º 24
0
int rc_if_fail_helper(struct radeon_compiler * c, const char * file, int line, const char * assertion)
{
	rc_error(c, "ICE at %s:%i: assertion failed: %s\n", file, line, assertion);
	return 1;
}
Exemplo n.º 25
0
static void translate_vertex_program(struct radeon_compiler *c, void *user)
{
	struct r300_vertex_program_compiler *compiler = (struct r300_vertex_program_compiler*)c;
	struct rc_instruction *rci;

	struct loop * loops = NULL;
	int current_loop_depth = 0;
	int loops_reserved = 0;

	unsigned int branch_depth = 0;

	compiler->code->pos_end = 0;	/* Not supported yet */
	compiler->code->length = 0;
	compiler->code->num_temporaries = 0;

	compiler->SetHwInputOutput(compiler);

	for(rci = compiler->Base.Program.Instructions.Next; rci != &compiler->Base.Program.Instructions; rci = rci->Next) {
		struct rc_sub_instruction *vpi = &rci->U.I;
		unsigned int *inst = compiler->code->body.d + compiler->code->length;
		const struct rc_opcode_info *info = rc_get_opcode_info(vpi->Opcode);

		/* Skip instructions writing to non-existing destination */
		if (!valid_dst(compiler->code, &vpi->DstReg))
			continue;

		if (info->HasDstReg) {
			/* Neither is Saturate. */
			if (vpi->SaturateMode != RC_SATURATE_NONE) {
				rc_error(&compiler->Base, "Vertex program does not support the Saturate "
					 "modifier (yet).\n");
			}
		}

		if (compiler->code->length >= c->max_alu_insts * 4) {
			rc_error(&compiler->Base, "Vertex program has too many instructions\n");
			return;
		}

		assert(compiler->Base.is_r500 ||
		       (vpi->Opcode != RC_OPCODE_SEQ &&
			vpi->Opcode != RC_OPCODE_SNE));

		switch (vpi->Opcode) {
		case RC_OPCODE_ADD: ei_vector2(compiler->code, VE_ADD, vpi, inst); break;
		case RC_OPCODE_ARL: ei_vector1(compiler->code, VE_FLT2FIX_DX, vpi, inst); break;
		case RC_OPCODE_COS: ei_math1(compiler->code, ME_COS, vpi, inst); break;
		case RC_OPCODE_DP4: ei_vector2(compiler->code, VE_DOT_PRODUCT, vpi, inst); break;
		case RC_OPCODE_DST: ei_vector2(compiler->code, VE_DISTANCE_VECTOR, vpi, inst); break;
		case RC_OPCODE_ELSE: ei_else(compiler, inst); break;
		case RC_OPCODE_ENDIF: ei_endif(compiler, inst); branch_depth--; break;
		case RC_OPCODE_EX2: ei_math1(compiler->code, ME_EXP_BASE2_FULL_DX, vpi, inst); break;
		case RC_OPCODE_EXP: ei_math1(compiler->code, ME_EXP_BASE2_DX, vpi, inst); break;
		case RC_OPCODE_FRC: ei_vector1(compiler->code, VE_FRACTION, vpi, inst); break;
		case RC_OPCODE_IF: ei_if(compiler, rci, inst, branch_depth); branch_depth++; break;
		case RC_OPCODE_LG2: ei_math1(compiler->code, ME_LOG_BASE2_FULL_DX, vpi, inst); break;
		case RC_OPCODE_LIT: ei_lit(compiler->code, vpi, inst); break;
		case RC_OPCODE_LOG: ei_math1(compiler->code, ME_LOG_BASE2_DX, vpi, inst); break;
		case RC_OPCODE_MAD: ei_mad(compiler->code, vpi, inst); break;
		case RC_OPCODE_MAX: ei_vector2(compiler->code, VE_MAXIMUM, vpi, inst); break;
		case RC_OPCODE_MIN: ei_vector2(compiler->code, VE_MINIMUM, vpi, inst); break;
		case RC_OPCODE_MOV: ei_vector1(compiler->code, VE_ADD, vpi, inst); break;
		case RC_OPCODE_MUL: ei_vector2(compiler->code, VE_MULTIPLY, vpi, inst); break;
		case RC_OPCODE_POW: ei_pow(compiler->code, vpi, inst); break;
		case RC_OPCODE_RCP: ei_math1(compiler->code, ME_RECIP_DX, vpi, inst); break;
		case RC_OPCODE_RSQ: ei_math1(compiler->code, ME_RECIP_SQRT_DX, vpi, inst); break;
		case RC_OPCODE_SEQ: ei_vector2(compiler->code, VE_SET_EQUAL, vpi, inst); break;
		case RC_OPCODE_SGE: ei_vector2(compiler->code, VE_SET_GREATER_THAN_EQUAL, vpi, inst); break;
		case RC_OPCODE_SIN: ei_math1(compiler->code, ME_SIN, vpi, inst); break;
		case RC_OPCODE_SLT: ei_vector2(compiler->code, VE_SET_LESS_THAN, vpi, inst); break;
		case RC_OPCODE_SNE: ei_vector2(compiler->code, VE_SET_NOT_EQUAL, vpi, inst); break;
		case RC_OPCODE_BGNLOOP:
		{
			struct loop * l;

			if ((!compiler->Base.is_r500
				&& loops_reserved >= R300_VS_MAX_LOOP_DEPTH)
				|| loops_reserved >= R500_VS_MAX_FC_DEPTH) {
				rc_error(&compiler->Base,
						"Loops are nested too deep.");
				return;
			}
			memory_pool_array_reserve(&compiler->Base.Pool,
					struct loop, loops, current_loop_depth,
					loops_reserved, 1);
			l = &loops[current_loop_depth++];
			memset(l , 0, sizeof(struct loop));
			l->BgnLoop = (compiler->code->length / 4);
			continue;
		}
		case RC_OPCODE_ENDLOOP:
		{
			struct loop * l;
			unsigned int act_addr;
			unsigned int last_addr;
			unsigned int ret_addr;

			assert(loops);
			l = &loops[current_loop_depth - 1];
			act_addr = l->BgnLoop - 1;
			last_addr = (compiler->code->length / 4) - 1;
			ret_addr = l->BgnLoop;

			if (loops_reserved >= R300_VS_MAX_FC_OPS) {
				rc_error(&compiler->Base,
					"Too many flow control instructions.");
				return;
			}
			if (compiler->Base.is_r500) {
				compiler->code->fc_op_addrs.r500
					[compiler->code->num_fc_ops].lw =
					R500_PVS_FC_ACT_ADRS(act_addr)
					| R500_PVS_FC_LOOP_CNT_JMP_INST(0xffff)
					;
				compiler->code->fc_op_addrs.r500
					[compiler->code->num_fc_ops].uw =
					R500_PVS_FC_LAST_INST(last_addr)
					| R500_PVS_FC_RTN_INST(ret_addr)
					;
			} else {
				compiler->code->fc_op_addrs.r300
					[compiler->code->num_fc_ops] =
					R300_PVS_FC_ACT_ADRS(act_addr)
					| R300_PVS_FC_LOOP_CNT_JMP_INST(0xff)
					| R300_PVS_FC_LAST_INST(last_addr)
					| R300_PVS_FC_RTN_INST(ret_addr)
					;
			}
			compiler->code->fc_loop_index[compiler->code->num_fc_ops] =
				R300_PVS_FC_LOOP_INIT_VAL(0x0)
				| R300_PVS_FC_LOOP_STEP_VAL(0x1)
				;
			compiler->code->fc_ops |= R300_VAP_PVS_FC_OPC_LOOP(
						compiler->code->num_fc_ops);
			compiler->code->num_fc_ops++;
			current_loop_depth--;
			continue;
		}

		default:
			rc_error(&compiler->Base, "Unknown opcode %s\n", info->Name);
			return;
		}

		/* Non-flow control instructions that are inside an if statement
		 * need to pay attention to the predicate bit. */
		if (branch_depth
			&& vpi->Opcode != RC_OPCODE_IF
			&& vpi->Opcode != RC_OPCODE_ELSE
			&& vpi->Opcode != RC_OPCODE_ENDIF) {

			inst[0] |= (PVS_DST_PRED_ENABLE_MASK
						<< PVS_DST_PRED_ENABLE_SHIFT);
			inst[0] |= (PVS_DST_PRED_SENSE_MASK
						<< PVS_DST_PRED_SENSE_SHIFT);
		}

		/* Update the number of temporaries. */
		if (info->HasDstReg && vpi->DstReg.File == RC_FILE_TEMPORARY &&
		    vpi->DstReg.Index >= compiler->code->num_temporaries)
			compiler->code->num_temporaries = vpi->DstReg.Index + 1;

		for (unsigned i = 0; i < info->NumSrcRegs; i++)
			if (vpi->SrcReg[i].File == RC_FILE_TEMPORARY &&
			    vpi->SrcReg[i].Index >= compiler->code->num_temporaries)
				compiler->code->num_temporaries = vpi->SrcReg[i].Index + 1;

		if (compiler->PredicateMask)
			if (compiler->PredicateIndex >= compiler->code->num_temporaries)
				compiler->code->num_temporaries = compiler->PredicateIndex + 1;

		if (compiler->code->num_temporaries > compiler->Base.max_temp_regs) {
			rc_error(&compiler->Base, "Too many temporaries.\n");
			return;
		}

		compiler->code->length += 4;

		if (compiler->Base.Error)
			return;
	}
}
Exemplo n.º 26
0
/**
 * @param c
 * @param loop
 * @param inst A pointer to a BGNLOOP instruction.
 * @return 1 if all of the members of loop where set.
 * @return 0 if there was an error and some members of loop are still NULL.
 */
static int build_loop_info(struct radeon_compiler * c, struct loop_info * loop,
						struct rc_instruction * inst)
{
	struct rc_instruction * ptr;

	if(inst->U.I.Opcode != RC_OPCODE_BGNLOOP){
		rc_error(c, "%s: expected BGNLOOP", __FUNCTION__);
		return 0;
	}

	memset(loop, 0, sizeof(struct loop_info));

	loop->BeginLoop = inst;

	for(ptr = loop->BeginLoop->Next; !loop->EndLoop; ptr = ptr->Next) {

		if (ptr == &c->Program.Instructions) {
			rc_error(c, "%s: BGNLOOP without an ENDLOOOP.\n",
								__FUNCTION__);
			return 0;
		}

		switch(ptr->U.I.Opcode){
		case RC_OPCODE_BGNLOOP:
		{
			/* Nested loop, skip ahead to the end. */
			unsigned int loop_depth = 1;
			for(ptr = ptr->Next; ptr != &c->Program.Instructions;
							ptr = ptr->Next){
				if (ptr->U.I.Opcode == RC_OPCODE_BGNLOOP) {
					loop_depth++;
				} else if (ptr->U.I.Opcode == RC_OPCODE_ENDLOOP) {
					if (!--loop_depth) {
						break;
					}
				}
			}
			if (ptr == &c->Program.Instructions) {
				rc_error(c, "%s: BGNLOOP without an ENDLOOOP\n",
								__FUNCTION__);
					return 0;
			}
			break;
		}
		case RC_OPCODE_BRK:
			if(ptr->Next->U.I.Opcode != RC_OPCODE_ENDIF
					|| ptr->Prev->U.I.Opcode != RC_OPCODE_IF
					|| loop->Brk){
				continue;
			}
			loop->Brk = ptr;
			loop->If = ptr->Prev;
			loop->EndIf = ptr->Next;
			switch(loop->If->Prev->U.I.Opcode){
			case RC_OPCODE_SLT:
			case RC_OPCODE_SGE:
			case RC_OPCODE_SGT:
			case RC_OPCODE_SLE:
			case RC_OPCODE_SEQ:
			case RC_OPCODE_SNE:
				break;
			default:
				return 0;
			}
			loop->Cond = loop->If->Prev;
			break;

		case RC_OPCODE_ENDLOOP:
			loop->EndLoop = ptr;
			break;
		}
	}

	if (loop->BeginLoop && loop->Brk && loop->If && loop->EndIf
					&& loop->Cond && loop->EndLoop) {
		return 1;
	}
	return 0;
}
Exemplo n.º 27
0
extern void doredirs() {
	List *fname;
	int fd, p[2];
	Rq *r;
	for (r = redirq; r != NULL; r = r->n) {
		switch(r->r->type) {
		default:
			panic("unexpected node in doredirs");
			/* NOTREACHED */
		case nRedir:
			if (r->r->u[0].i == rHerestring) {
				fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */
				if (pipe(p) < 0) {
					uerror("pipe");
					rc_error(NULL);
				}
				if (rc_fork() == 0) { /* child writes to pipe */
					setsigdefaults(FALSE);
					close(p[0]);
					if (fname != NULL)
						writeall(p[1], fname->w, strlen(fname->w));
					exit(0);
				} else {
					close(p[1]);
					if (mvfd(p[0], r->r->u[1].i) < 0)
						rc_error(NULL);
				}
			} else {
				fname = glob(glom(r->r->u[2].p));
				if (fname == NULL)
					rc_error("null filename in redirection");
				if (fname->n != NULL)
					rc_error("multi-word filename in redirection");
				switch (r->r->u[0].i) {
				default:
					panic("unexpected node in doredirs");
					/* NOTREACHED */
				case rCreate: case rAppend: case rFrom:
					fd = rc_open(fname->w, r->r->u[0].i);
					break;
				}
				if (fd < 0) {
					uerror(fname->w);
					rc_error(NULL);
				}
				if (mvfd(fd, r->r->u[1].i) < 0)
					rc_error(NULL);
			}
			break;
		case nDup:
			if (r->r->u[2].i == -1)
				close(r->r->u[1].i);
			else if (r->r->u[2].i != r->r->u[1].i) {
				if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) {
					uerror("dup2");
					rc_error(NULL);
				}
			}
		}
	}
	redirq = NULL;
}
Exemplo n.º 28
0
/**
 * Emit one paired ALU instruction.
 */
static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* inst)
{
	int ip;
	int j;
	PROG_CODE;

	if (code->alu.length >= c->Base.max_alu_insts) {
		error("Too many ALU instructions");
		return 0;
	}

	ip = code->alu.length++;

	code->alu.inst[ip].rgb_inst = translate_rgb_opcode(c, inst->RGB.Opcode);
	code->alu.inst[ip].alpha_inst = translate_alpha_opcode(c, inst->Alpha.Opcode);

	for(j = 0; j < 3; ++j) {
		/* Set the RGB address */
		unsigned int src = use_source(code, inst->RGB.Src[j]);
		unsigned int arg;
		if (inst->RGB.Src[j].Index >= R300_PFS_NUM_TEMP_REGS)
			code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_RGB_MSB_BIT(j);

		code->alu.inst[ip].rgb_addr |= src << (6*j);

		/* Set the Alpha address */
		src = use_source(code, inst->Alpha.Src[j]);
		if (inst->Alpha.Src[j].Index >= R300_PFS_NUM_TEMP_REGS)
			code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_A_MSB_BIT(j);

		code->alu.inst[ip].alpha_addr |= src << (6*j);

		arg = r300FPTranslateRGBSwizzle(inst->RGB.Arg[j].Source, inst->RGB.Arg[j].Swizzle);
		arg |= inst->RGB.Arg[j].Abs << 6;
		arg |= inst->RGB.Arg[j].Negate << 5;
		code->alu.inst[ip].rgb_inst |= arg << (7*j);

		arg = r300FPTranslateAlphaSwizzle(inst->Alpha.Arg[j].Source, inst->Alpha.Arg[j].Swizzle);
		arg |= inst->Alpha.Arg[j].Abs << 6;
		arg |= inst->Alpha.Arg[j].Negate << 5;
		code->alu.inst[ip].alpha_inst |= arg << (7*j);
	}

	/* Presubtract */
	if (inst->RGB.Src[RC_PAIR_PRESUB_SRC].Used) {
		switch(inst->RGB.Src[RC_PAIR_PRESUB_SRC].Index) {
		case RC_PRESUB_BIAS:
			code->alu.inst[ip].rgb_inst |=
						R300_ALU_SRCP_1_MINUS_2_SRC0;
			break;
		case RC_PRESUB_ADD:
			code->alu.inst[ip].rgb_inst |=
						R300_ALU_SRCP_SRC1_PLUS_SRC0;
			break;
		case RC_PRESUB_SUB:
			code->alu.inst[ip].rgb_inst |=
						R300_ALU_SRCP_SRC1_MINUS_SRC0;
			break;
		case RC_PRESUB_INV:
			code->alu.inst[ip].rgb_inst |=
						R300_ALU_SRCP_1_MINUS_SRC0;
			break;
		default:
			break;
		}
	}

	if (inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Used) {
		switch(inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) {
		case RC_PRESUB_BIAS:
			code->alu.inst[ip].alpha_inst |=
						R300_ALU_SRCP_1_MINUS_2_SRC0;
			break;
		case RC_PRESUB_ADD:
			code->alu.inst[ip].alpha_inst |=
						R300_ALU_SRCP_SRC1_PLUS_SRC0;
			break;
		case RC_PRESUB_SUB:
			code->alu.inst[ip].alpha_inst |=
						R300_ALU_SRCP_SRC1_MINUS_SRC0;
			break;
		case RC_PRESUB_INV:
			code->alu.inst[ip].alpha_inst |=
						R300_ALU_SRCP_1_MINUS_SRC0;
			break;
		default:
			break;
		}
	}

	if (inst->RGB.Saturate)
		code->alu.inst[ip].rgb_inst |= R300_ALU_OUTC_CLAMP;
	if (inst->Alpha.Saturate)
		code->alu.inst[ip].alpha_inst |= R300_ALU_OUTA_CLAMP;

	if (inst->RGB.WriteMask) {
		use_temporary(code, inst->RGB.DestIndex);
		if (inst->RGB.DestIndex >= R300_PFS_NUM_TEMP_REGS)
			code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_RGB_MSB_BIT;
		code->alu.inst[ip].rgb_addr |=
			((inst->RGB.DestIndex & 0x1f) << R300_ALU_DSTC_SHIFT) |
			(inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT);
	}
	if (inst->RGB.OutputWriteMask) {
		code->alu.inst[ip].rgb_addr |=
            (inst->RGB.OutputWriteMask << R300_ALU_DSTC_OUTPUT_MASK_SHIFT) |
            R300_RGB_TARGET(inst->RGB.Target);
		emit->node_flags |= R300_RGBA_OUT;
	}

	if (inst->Alpha.WriteMask) {
		use_temporary(code, inst->Alpha.DestIndex);
		if (inst->Alpha.DestIndex >= R300_PFS_NUM_TEMP_REGS)
			code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_A_MSB_BIT;
		code->alu.inst[ip].alpha_addr |=
			((inst->Alpha.DestIndex & 0x1f) << R300_ALU_DSTA_SHIFT) |
			R300_ALU_DSTA_REG;
	}
	if (inst->Alpha.OutputWriteMask) {
		code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_OUTPUT |
            R300_ALPHA_TARGET(inst->Alpha.Target);
		emit->node_flags |= R300_RGBA_OUT;
	}
	if (inst->Alpha.DepthWriteMask) {
		code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_DEPTH;
		emit->node_flags |= R300_W_OUT;
		c->code->writes_depth = 1;
	}
	if (inst->Nop)
		code->alu.inst[ip].rgb_inst |= R300_ALU_INSERT_NOP;

	/* Handle Output Modifier
	 * According to the r300 docs, there is no RC_OMOD_DISABLE for r300 */
	if (inst->RGB.Omod) {
		if (inst->RGB.Omod == RC_OMOD_DISABLE) {
			rc_error(&c->Base, "RC_OMOD_DISABLE not supported");
		}
		code->alu.inst[ip].rgb_inst |=
			(inst->RGB.Omod << R300_ALU_OUTC_MOD_SHIFT);
	}
	if (inst->Alpha.Omod) {
		if (inst->Alpha.Omod == RC_OMOD_DISABLE) {
			rc_error(&c->Base, "RC_OMOD_DISABLE not supported");
		}
		code->alu.inst[ip].alpha_inst |=
			(inst->Alpha.Omod << R300_ALU_OUTC_MOD_SHIFT);
	}
	return 1;
}
Exemplo n.º 29
0
static struct r300_vertex_program *build_program(GLcontext *ctx,
						 struct r300_vertex_program_key *wanted_key,
						 const struct gl_vertex_program *mesa_vp)
{
	struct r300_vertex_program *vp;
	struct r300_vertex_program_compiler compiler;

	vp = _mesa_calloc(sizeof(*vp));
	vp->Base = (struct gl_vertex_program *) _mesa_clone_program(ctx, &mesa_vp->Base);
	_mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));

	rc_init(&compiler.Base);
	compiler.Base.Debug = (RADEON_DEBUG & RADEON_VERTS) ? GL_TRUE : GL_FALSE;

	compiler.code = &vp->code;
	compiler.RequiredOutputs = compute_required_outputs(vp->Base, vp->key.FpReads);
	compiler.SetHwInputOutput = &t_inputs_outputs;

	if (compiler.Base.Debug) {
		fprintf(stderr, "Initial vertex program:\n");
		_mesa_print_program(&vp->Base->Base);
		fflush(stderr);
	}

	if (mesa_vp->IsPositionInvariant) {
		_mesa_insert_mvp_code(ctx, vp->Base);
	}

	radeon_mesa_to_rc_program(&compiler.Base, &vp->Base->Base);

	if (mesa_vp->IsNVProgram)
		initialize_NV_registers(&compiler.Base);

	rc_move_output(&compiler.Base, VERT_RESULT_PSIZ, VERT_RESULT_PSIZ, WRITEMASK_X);

	if (vp->key.WPosAttr != FRAG_ATTRIB_MAX) {
		rc_copy_output(&compiler.Base,
			VERT_RESULT_HPOS,
			vp->key.WPosAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0);
	}

	if (vp->key.FogAttr != FRAG_ATTRIB_MAX) {
		rc_move_output(&compiler.Base,
			VERT_RESULT_FOGC,
			vp->key.FogAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0, WRITEMASK_X);
	}

	r3xx_compile_vertex_program(&compiler);

	if (vp->code.constants.Count > ctx->Const.VertexProgram.MaxParameters) {
		rc_error(&compiler.Base, "Program exceeds constant buffer size limit\n");
	}

	vp->error = compiler.Base.Error;

	vp->Base->Base.InputsRead = vp->code.InputsRead;
	vp->Base->Base.OutputsWritten = vp->code.OutputsWritten;

	rc_destroy(&compiler.Base);

	return vp;
}
Exemplo n.º 30
0
/**
 * Final compilation step: Turn the intermediate radeon_program into
 * machine-readable instructions.
 */
void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
{
	struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c;
	struct r300_emit_state emit;
	struct r300_fragment_program_code *code = &compiler->code->code.r300;
	unsigned int tex_end;

	memset(&emit, 0, sizeof(emit));
	emit.compiler = compiler;

	memset(code, 0, sizeof(struct r300_fragment_program_code));

	for(struct rc_instruction * inst = compiler->Base.Program.Instructions.Next;
	    inst != &compiler->Base.Program.Instructions && !compiler->Base.Error;
	    inst = inst->Next) {
		if (inst->Type == RC_INSTRUCTION_NORMAL) {
			if (inst->U.I.Opcode == RC_OPCODE_BEGIN_TEX) {
				begin_tex(&emit);
				continue;
			}

			emit_tex(&emit, inst);
		} else {
			emit_alu(&emit, &inst->U.P);
		}
	}

	if (code->pixsize >= compiler->Base.max_temp_regs)
		rc_error(&compiler->Base, "Too many hardware temporaries used.\n");

	if (compiler->Base.Error)
		return;

	/* Finish the program */
	finish_node(&emit);

	code->config |= emit.current_node; /* FIRST_NODE_HAS_TEX set by finish_node */

	/* Set r400 extended instruction fields.  These values will be ignored
	 * on r300 cards. */
	code->r400_code_offset_ext |=
		(get_msbs_alu(0)
				<< R400_ALU_OFFSET_MSB_SHIFT)
		| (get_msbs_alu(code->alu.length - 1)
				<< R400_ALU_SIZE_MSB_SHIFT);

	tex_end = code->tex.length ? code->tex.length - 1 : 0;
	code->code_offset =
		((0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT)
			& R300_PFS_CNTL_ALU_OFFSET_MASK)
		| (((code->alu.length - 1) << R300_PFS_CNTL_ALU_END_SHIFT)
			& R300_PFS_CNTL_ALU_END_MASK)
		| ((0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT)
			& R300_PFS_CNTL_TEX_OFFSET_MASK)
		| ((tex_end << R300_PFS_CNTL_TEX_END_SHIFT)
			& R300_PFS_CNTL_TEX_END_MASK)
		| (get_msbs_tex(0, 5) << R400_TEX_START_MSB_SHIFT)
		| (get_msbs_tex(tex_end, 6) << R400_TEX_SIZE_MSB_SHIFT)
		;

	if (emit.current_node < 3) {
		int shift = 3 - emit.current_node;
		int i;
		for(i = emit.current_node; i >= 0; --i)
			code->code_addr[shift + i] = code->code_addr[i];
		for(i = 0; i < shift; ++i)
			code->code_addr[i] = 0;
	}

	if (code->pixsize >= R300_PFS_NUM_TEMP_REGS
	    || code->alu.length > R300_PFS_MAX_ALU_INST
	    || code->tex.length > R300_PFS_MAX_TEX_INST) {

		code->r390_mode = 1;
	}
}