uforth_stat exec(CELL wd_idx, char toplevelprim,uint8_t last_exec_rdix) { while(1) { if (wd_idx == 0) { uforth_abort_request(ABORT_ILLEGAL); uforth_abort(); /* bad instruction */ return E_NOT_A_WORD; } cmd = uforth_dict[wd_idx++]; switch (cmd) { case 0: uforth_abort_request(ABORT_ILLEGAL); uforth_abort(); /* bad instruction */ return E_NOT_A_WORD; case ABORT: uforth_abort_request(ABORT_WORD); break; case IMMEDIATE: make_immediate(); break; case IRAM_FETCH: r1 = dpop(); dpush(((DCELL*)uforth_iram)[r1]); break; case URAM_BASE_ADDR: dpush((RAM_START_IDX + (sizeof(struct uforth_iram))) + curtask_idx); break; case SKIP_IF_ZERO: r1 = dpop(); r2 = dpop(); if (r2 == 0) wd_idx += r1; break; case DROP: dpop(); break; case JMP: wd_idx = dpop(); break; case JMP_IF_ZERO: r1 = dpop(); r2 = dpop(); if (r2 == 0) wd_idx = r1; break; case HERE: dpush(dict_here()); break; case INCR_HERE: dict_incr_here(1); break; case LIT: dpush(uforth_dict[wd_idx++]); break; case DLIT: dpush((((uint32_t)uforth_dict[wd_idx])<<16) | (uint16_t)uforth_dict[wd_idx+1]); wd_idx+=2; break; case LESS_THAN: r1 = dpop(); r2 = dpop(); dpush(r2 < r1); break; case ABS: r1 = dpop(); dpush(abs32(r1)); break; case ADD: r1 = dpop(); r2 = dtop(); dtop() = r1+r2; break; case SUB: r1 = dpop(); r2 = dtop(); dtop() = r2-r1; break; case AND: r1 = dpop(); r2 = dtop(); dtop() = r1&r2; break; case LSHIFT: r1 = dpop(); r2 = dtop(); dtop() = r2<<r1; break; case RSHIFT: r1 = dpop(); r2 = dtop(); dtop() = r2>>r1; break; case OR: r1 = dpop(); r2 = dtop(); dtop() = r1|r2; break; case XOR: r1 = dpop(); r2 = dtop(); dtop() = r1^r2; break; case INVERT: dtop() = ~dtop(); break; case MULT: r1 = dpop(); r2 = dtop(); dtop() = r1*r2; break; case DIV : r1 = dpop(); r2 = dtop(); dtop() = r2/r1; break; case SWAP: r1 = dpop(); r2 = dpop(); dpush(r1); dpush(r2); break; case RPICK: r1 = dpop(); r2 = rpick(r1); dpush(r2); break; case PICK: r1 = dpop(); r2 = dpick(r1); dpush(r2); break; case EQ_ZERO: dtop() = (dtop() == 0); break; case RPUSH: rpush(dpop()); break; case RPOP: dpush(rpop()); break; case FETCH: r1 = dpop(); if (r1 >= RAM_START_IDX) { dpush(uforth_ram[r1-RAM_START_IDX]); } else { dpush(uforth_dict[r1]); } break; case STORE: r1 = dpop(); r2 = dpop(); if (r1 >= RAM_START_IDX) { uforth_ram[r1-RAM_START_IDX] = r2; } else { dict_write(r1,r2); } break; case EXEC: r1 = dpop(); rpush(wd_idx); wd_idx = r1; break; case EXIT: if (uforth_uram->ridx > last_exec_rdix) return OK; wd_idx = rpop(); break; case CNEXT: b = next_char(); dpush(b); break; case STR_STORE: r1 = dpop(); r2 = uforth_ram[(r1-RAM_START_IDX)]; str1 =(char*)&uforth_ram[(r1-RAM_START_IDX)+1]; str1+=r2; b = dpop(); *str1 = b; uforth_ram[(r1-RAM_START_IDX)]++; break; case NEXT: str2 = PAD_STR; str1 = uforth_next_word(); memcpy(str2,str1, uforth_iram->currwordlen); PAD_STRLEN = uforth_iram->currwordlen; /* length */ dpush(PAD_ADDR+RAM_START_IDX); break; case COMMA_STRING: if (uforth_iram->compiling > 0) { dict_append(LIT); dict_append(dict_here()+4); /* address of counted string */ dict_append(LIT); rpush(dict_here()); /* address holding adress */ dict_incr_here(1); /* place holder for jump address */ dict_append(JMP); } rpush(dict_here()); dict_incr_here(1); /* place holder for count*/ r1 = 0; b = next_char(); /* eat space */ while (b != 0 && b!= '"') { r2 = 0; b = next_char(); if (b == 0 || b == '"') break; r2 |= BYTEPACK_FIRST(b); ++r1; b = next_char(); if (b != 0 && b != '"') { ++r1; r2 |= BYTEPACK_SECOND(b); } dict_append(r2); } dict_write(rpop(),r1); if (uforth_iram->compiling > 0) { dict_write(rpop(),dict_here()); /* jump over string */ } break; case CALLC: r1 = c_handle(); if (r1 != OK) return (uforth_stat)r1; break; case VAR_ALLOT: dpush(VAR_ALLOT_1()); break; case DEF: uforth_iram->compiling = 1; case _CREATE: dict_start_def(); uforth_next_word(); make_word(uforth_iram->currword,uforth_iram->currwordlen); if (cmd == _CREATE) { dict_end_def(); } else { defining_word = dict_here(); } break; case COMMA: dict_append(dpop()); break; case DCOMMA: r1 = dpop(); dict_append((uint32_t)r1>>16); dict_append(r1); break; case PARSE_NUM: r1 = dpop(); str1=uforth_count_str((CELL)r1,(CELL*)&r1); str1[r1] = '\0'; dpush(parse_num(str1,uforth_uram->base)); break; case PARSE_FNUM: r1 = dpop(); str1=uforth_count_str((CELL)r1,(CELL*)&r1); str1[r1] = '.'; str1[r1+1] = '\0'; dpush(parse_num(str1,uforth_uram->base)); break; case FIND: case FIND_ADDR: r1 = dpop(); str1=uforth_count_str((CELL)r1,(CELL*)&r1); r1 = find_word(str1, r1, &r2, 0, &b); if (r1 > 0) { if (b) r1 = uforth_dict[r1]; } if (cmd == FIND) { dpush(r1); } else { dpush(r2); } break; case POSTPONE: str1 = uforth_next_word(); r1 = find_word(str1, uforth_iram->currwordlen, 0, 0, &b); if (r1 == 0) { uforth_abort_request(ABORT_NAW); uforth_abort(); return E_NOT_A_WORD; } if (b) { dict_append(uforth_dict[r1]); } else { dict_append(r1); } break; case MOVE: r1 = dpop(); /* count */ rpush(r1); r1 = dpop(); /* dest */ r2 = dpop(); /* source */ if (r1 < RAM_START_IDX) { (void)rpop(); uforth_abort_request(ABORT_ILLEGAL); uforth_abort(); /* can't cmove into dictionary */ return E_ABORT; } str1 =(char*)&uforth_ram[(r1-RAM_START_IDX)]; if (r2 > RAM_START_IDX) { str2 =(char*)&uforth_ram[(r2-RAM_START_IDX)]; } else { str2 = (char*)&uforth_dict[r2]; } memcpy(str1, str2, rpop()); break; case MAKE_TASK: r1 = dpop(); r2 = dpop(); r3 = dpop(); r4 = dpop(); uforth_make_task(r1-RAM_START_IDX, r2, r3, r4); dpush(r1-RAM_START_IDX); break; case SELECT_TASK: uforth_select_task(dpop()); break; default: /* Execute user word by calling until we reach primitives */ rpush(wd_idx); wd_idx = uforth_dict[wd_idx-1]; /* wd_idx-1 is current word */ break; } if (uforth_aborting()) { uforth_abort(); return E_ABORT; } if (toplevelprim) return OK; } /* while(1) */ }
/** * Translate Mesa program to TGSI format. * \param program the program to translate * \param numInputs number of input registers used * \param inputMapping maps Mesa fragment program inputs to TGSI generic * input indexes * \param inputSemanticName the TGSI_SEMANTIC flag for each input * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input * \param numOutputs number of output registers used * \param outputMapping maps Mesa fragment program outputs to TGSI * generic outputs * \param outputSemanticName the TGSI_SEMANTIC flag for each output * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output * \param tokens array to store translated tokens in * \param maxTokens size of the tokens array * * \return number of tokens placed in 'tokens' buffer, or zero if error */ GLuint st_translate_mesa_program( GLcontext *ctx, uint procType, const struct gl_program *program, GLuint numInputs, const GLuint inputMapping[], const ubyte inputSemanticName[], const ubyte inputSemanticIndex[], const GLuint interpMode[], const GLbitfield inputFlags[], GLuint numOutputs, const GLuint outputMapping[], const ubyte outputSemanticName[], const ubyte outputSemanticIndex[], const GLbitfield outputFlags[], struct tgsi_token *tokens, GLuint maxTokens ) { GLuint i; GLuint ti; /* token index */ struct tgsi_header *header; struct tgsi_processor *processor; GLuint preamble_size = 0; GLuint immediates[1000]; GLuint numImmediates = 0; GLboolean insideSubroutine = GL_FALSE; GLboolean indirectAccess = GL_FALSE; GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1]; GLint wposTemp = -1, winHeightConst = -1; assert(procType == TGSI_PROCESSOR_FRAGMENT || procType == TGSI_PROCESSOR_VERTEX); find_temporaries(program, tempsUsed); if (procType == TGSI_PROCESSOR_FRAGMENT) { if (program->InputsRead & FRAG_BIT_WPOS) { /* Fragment program uses fragment position input. * Need to replace instances of INPUT[WPOS] with temp T * where T = INPUT[WPOS] by y is inverted. */ static const gl_state_index winSizeState[STATE_LENGTH] = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0 }; winHeightConst = _mesa_add_state_reference(program->Parameters, winSizeState); wposTemp = find_free_temporary(tempsUsed); } } *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); header = (struct tgsi_header *) &tokens[1]; *header = tgsi_build_header(); processor = (struct tgsi_processor *) &tokens[2]; *processor = tgsi_build_processor( procType, header ); ti = 3; /* * Declare input attributes. */ if (procType == TGSI_PROCESSOR_FRAGMENT) { for (i = 0; i < numInputs; i++) { struct tgsi_full_declaration fulldecl; fulldecl = make_input_decl(i, GL_TRUE, interpMode[i], TGSI_WRITEMASK_XYZW, GL_TRUE, inputSemanticName[i], inputSemanticIndex[i], inputFlags[i]); ti += tgsi_build_full_declaration(&fulldecl, &tokens[ti], header, maxTokens - ti ); } } else { /* vertex prog */ /* XXX: this could probaby be merged with the clause above. * the only difference is the semantic tags. */ for (i = 0; i < numInputs; i++) { struct tgsi_full_declaration fulldecl; fulldecl = make_input_decl(i, GL_FALSE, 0, TGSI_WRITEMASK_XYZW, GL_FALSE, 0, 0, inputFlags[i]); ti += tgsi_build_full_declaration(&fulldecl, &tokens[ti], header, maxTokens - ti ); } } /* * Declare output attributes. */ if (procType == TGSI_PROCESSOR_FRAGMENT) { for (i = 0; i < numOutputs; i++) { struct tgsi_full_declaration fulldecl; switch (outputSemanticName[i]) { case TGSI_SEMANTIC_POSITION: fulldecl = make_output_decl(i, TGSI_SEMANTIC_POSITION, /* Z / Depth */ outputSemanticIndex[i], TGSI_WRITEMASK_Z, outputFlags[i]); break; case TGSI_SEMANTIC_COLOR: fulldecl = make_output_decl(i, TGSI_SEMANTIC_COLOR, outputSemanticIndex[i], TGSI_WRITEMASK_XYZW, outputFlags[i]); break; default: assert(0); return 0; } ti += tgsi_build_full_declaration(&fulldecl, &tokens[ti], header, maxTokens - ti ); } } else { /* vertex prog */ for (i = 0; i < numOutputs; i++) { struct tgsi_full_declaration fulldecl; fulldecl = make_output_decl(i, outputSemanticName[i], outputSemanticIndex[i], TGSI_WRITEMASK_XYZW, outputFlags[i]); ti += tgsi_build_full_declaration(&fulldecl, &tokens[ti], header, maxTokens - ti ); } } /* temporary decls */ { GLboolean inside_range = GL_FALSE; GLuint start_range = 0; tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE; for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) { if (tempsUsed[i] && !inside_range) { inside_range = GL_TRUE; start_range = i; } else if (!tempsUsed[i] && inside_range) { struct tgsi_full_declaration fulldecl; inside_range = GL_FALSE; fulldecl = make_temp_decl( start_range, i - 1 ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], header, maxTokens - ti ); } } } /* Declare address register. */ if (program->NumAddressRegs > 0) { struct tgsi_full_declaration fulldecl; assert( program->NumAddressRegs == 1 ); fulldecl = make_addr_decl( 0, 0 ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], header, maxTokens - ti ); indirectAccess = GL_TRUE; } /* immediates/literals */ memset(immediates, ~0, sizeof(immediates)); /* Emit immediates only when there is no address register in use. * FIXME: Be smarter and recognize param arrays -- indirect addressing is * only valid within the referenced array. */ if (program->Parameters && !indirectAccess) { for (i = 0; i < program->Parameters->NumParameters; i++) { if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) { struct tgsi_full_immediate fullimm; fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 ); ti += tgsi_build_full_immediate( &fullimm, &tokens[ti], header, maxTokens - ti ); immediates[i] = numImmediates; numImmediates++; } } } /* constant buffer refs */ if (program->Parameters) { GLint start = -1, end = -1; for (i = 0; i < program->Parameters->NumParameters; i++) { GLboolean emit = (i == program->Parameters->NumParameters - 1); GLboolean matches; switch (program->Parameters->Parameters[i].Type) { case PROGRAM_ENV_PARAM: case PROGRAM_STATE_VAR: case PROGRAM_NAMED_PARAM: case PROGRAM_UNIFORM: matches = GL_TRUE; break; case PROGRAM_CONSTANT: matches = indirectAccess; break; default: matches = GL_FALSE; } if (matches) { if (start == -1) { /* begin a sequence */ start = i; end = i; } else { /* continue sequence */ end = i; } } else { if (start != -1) { /* end of sequence */ emit = GL_TRUE; } } if (emit && start >= 0) { struct tgsi_full_declaration fulldecl; fulldecl = make_constant_decl( start, end ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], header, maxTokens - ti ); start = end = -1; } } } /* texture samplers */ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { if (program->SamplersUsed & (1 << i)) { struct tgsi_full_declaration fulldecl; fulldecl = make_sampler_decl( i ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], header, maxTokens - ti ); } } /* invert WPOS fragment input */ if (wposTemp >= 0) { ti += emit_inverted_wpos(&tokens[ti], wposTemp, winHeightConst, inputMapping[FRAG_ATTRIB_WPOS], header, maxTokens - ti); preamble_size = 2; /* two instructions added */ } for (i = 0; i < program->NumInstructions; i++) { struct tgsi_full_instruction fullinst; compile_instruction( &program->Instructions[i], &fullinst, inputMapping, outputMapping, immediates, indirectAccess, preamble_size, procType, &insideSubroutine, wposTemp); ti += tgsi_build_full_instruction( &fullinst, &tokens[ti], header, maxTokens - ti ); } #if DEBUG if(!tgsi_sanity_check(tokens)) { debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n"); debug_printf("\nOriginal program:\n%s", program->String); debug_printf("\nMesa program:\n"); _mesa_print_program(program); debug_printf("\nTGSI program:\n"); tgsi_dump(tokens, 0); assert(0); } #endif return ti; }
void uforth_init(void) { uforth_dict = (CELL*)dict; uforth_iram = (struct uforth_iram*) uforth_ram; uforth_iram->compiling = 0; uforth_iram->total_ram = TOTAL_RAM_CELLS; uforth_make_task(0,TASK0_DS_CELLS,TASK0_RS_CELLS,TASK0_URAM_CELLS); uforth_select_task(0); uforth_abort_clr(); uforth_abort(); uforth_uram->base = 10; #ifdef BOOTSTRAP dict->here = DICT_HEADER_WORDS+1; /* Store our primitives into the dictionary. */ store_prim("cf", CALLC); store_prim("uram", URAM_BASE_ADDR); store_prim("+iram@", IRAM_FETCH); store_prim("immediate", IMMEDIATE); store_prim("abort", ABORT); store_prim("pick", PICK); store_prim("rpick", RPICK); store_prim("swap", SWAP); store_prim("0skip?", SKIP_IF_ZERO); store_prim("drop", DROP); store_prim("jmp", JMP); store_prim("0jmp?", JMP_IF_ZERO); store_prim("exec", EXEC); store_prim(",", COMMA); store_prim("d,", DCOMMA); store_prim(">num", PARSE_NUM); store_prim(">fnum", PARSE_FNUM); store_prim("dummy,", INCR_HERE); store_prim("abs", ABS); store_prim("+", ADD); store_prim("-", SUB); store_prim("and", AND); store_prim("or", OR); store_prim("xor", XOR); store_prim("invert", INVERT); store_prim("lshift", LSHIFT); store_prim("rshift", RSHIFT); store_prim("*", MULT); store_prim("/", DIV); store_prim("0=", EQ_ZERO); store_prim("lit", LIT); store_prim("dlit", DLIT); store_prim(">r", RPUSH); store_prim("r>", RPOP); store_prim("@", FETCH); store_prim("!", STORE); store_prim(";", EXIT); make_immediate(); store_prim(":", DEF); store_prim("_create", _CREATE); store_prim("_allot1", VAR_ALLOT); store_prim("make-task", MAKE_TASK); store_prim("select-task", SELECT_TASK); store_prim("(find)", FIND); store_prim("(find&)", FIND_ADDR); store_prim(",\"", COMMA_STRING); make_immediate(); store_prim("postpone", POSTPONE); make_immediate(); store_prim("next-word", NEXT); store_prim("next-char", CNEXT); store_prim("str++", STR_STORE); store_prim("move", MOVE); store_prim("here", HERE); store_prim("<", LESS_THAN); #endif }