void generate_FUNCSTART(quad* quad){ struct instruction t0; t0.arg1.type = nil_a; t0.arg2.type = nil_a; t0.result.type= label_a; t0.result.val = 0; t0.opcode = jump_v; add_func_jump(nextinstructionlabel()); emit_instruction(&t0); struct userfunc* f; f = (struct userfunc*)malloc(sizeof(struct userfunc)); f->id=quad->result->sym->name; f->address = nextinstructionlabel(); quad->taddress = nextinstructionlabel(); userfuncs_newfunc(quad->result->sym); //added 6/5 ore (userFuncs+totalUserFuncs)->address = f->address; (userFuncs+totalUserFuncs)->id = f->id; (userFuncs+totalUserFuncs)->localSize = quad->result->sym->totallocals; f->index = totalUserFuncs-1; funcpush(f); struct instruction t; totalUserFuncs++; t.arg1.type = nil_a; t.arg2.type = nil_a; t.opcode = funcenter_v; make_operand(quad->result, &t.result); t.result.val = totalUserFuncs-1; //EDW emit_instruction(&t); }
void generate_OR (quad* quad) { quad->taddress = nextinstructionlabel(); struct instruction t; t.opcode = jeq_v; make_operand(quad->arg1, &t.arg1); make_booloperand(&t.arg2, '1'); t.result.type = label_a; t.result.val = nextinstructionlabel()+4; emit_instruction(&t); make_operand(quad->arg2, &t.arg1); t.result.val = nextinstructionlabel()+3; emit_instruction(&t); t.opcode = assign_v; make_booloperand(&t.arg1, '0'); reset_operand(&t.arg2); make_operand(quad->result, &t.result); emit_instruction(&t); t.opcode = jump_v; reset_operand (&t.arg1); reset_operand(&t.arg2); t.result.type = label_a; t.result.val = nextinstructionlabel()+2; emit_instruction(&t); t.opcode = assign_v; make_booloperand(&t.arg1, '1'); reset_operand(&t.arg2); make_operand(quad->result, &t.result); emit_instruction(&t); }
static bool generate_output() { size_t n; uint16_t C, A; /* Write header */ write_data(MAGIC_STR, MAGIC_LEN); /* Generate instructions */ C = A = 0; for (n = 0; n < last_num_blocks; ++n) { if (last_blocks[n].is == NULL) { /* Check to see if we must start a new instruction */ if ( (C > 0 && last_blocks[n].offset != last_blocks[n - 1].offset + BS ) || (C == 0x7fffu) || (A > 0) ) { emit_instruction(n, C, A); C = A = 0; } ++C; } else { if (A == 0x7fffu) { emit_instruction(n, C, A); C = A = 0; } ++A; } } /* Emit final instruction (if necessary) */ if (C > 0 || A > 0) emit_instruction(last_num_blocks, C, A); /* Write end-of-instructions */ write_uint32(0xffffffffu); write_uint16(0xffffu); write_uint16(0xffffu); /* Add last file digest */ write_data(last_digest, DS); /* Add first file digest (if known) */ if (!orig_digest_known) { fprintf(stderr, "WARNING: original file digest unknown; " "generating version 1.0 differences file.\n"); } else { write_data(orig_digest, DS); } return true; }
/** * Declare a VS input register. * We still make up the input semantics the same as in 2.0 */ static boolean vs30_input(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; unsigned usage, index; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); assert(dcl.dst.reserved0); svga_generate_vdecl_semantics( idx, &usage, &index ); dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
static boolean vs20_input( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); assert(dcl.dst.reserved0); /* Mesa doesn't provide use with VS input semantics (they're * actually pretty meaningless), so we just generate some plausible * ones here. This has to match what we declare in the vdecl code * in svga_pipe_vertex.c. */ if (idx == 0) { dcl.usage = SVGA3D_DECLUSAGE_POSITION; dcl.index = 0; } else { dcl.usage = SVGA3D_DECLUSAGE_TEXCOORD; dcl.index = idx - 1; } dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
/** * Emit a PS input (or VS depth/fog output) register declaration. * For example, if usage = SVGA3D_DECLUSAGE_TEXCOORD, reg.num = 1, and * index = 3, we'll emit "dcl_texcoord3 v1". */ static boolean emit_decl(struct svga_shader_emitter *emit, SVGA3dShaderDestToken reg, unsigned usage, unsigned index) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; /* check values against bitfield sizes */ assert(index < 16); assert(usage <= SVGA3D_DECLUSAGE_MAX); opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; dcl.dst = reg; dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
/* * Main function - glue everything together. */ int main ( int argc, char **argv ) { // Initialize the state machine (if neccessary) init_transtab (); // Print a bit of startup, to start drawing somewhere sensible printf ( "newpath\n%d %d moveto\n", x, y ); // Make sure the loop below runs at least once (the value given // here will be discarded in the first iteration) command_t c = MOVE; //Test commands /*draw(); turn(); draw(); move(); draw();*/ // Until the end of the input stream, while ( c != END ) { c = next(stdin); // Read until we have a token emit_instruction(c); // Emit the instruction it stands for } // Finalize by drawing the traced path, and exiting printf ( "stroke\nshowpage\n" ); exit ( EXIT_SUCCESS ); }
void generate_GETRETVAL(quad* quad) { quad->taddress = nextinstructionlabel(); struct instruction t; t.opcode = assign_v; make_operand(quad->result, &t.result); make_retvaloperand(&t.arg1); emit_instruction(&t); }
void generate_CALL(quad* quad) { quad->taddress = nextinstructionlabel(); struct instruction t; t.opcode = call_v; t.arg1.type = nil_a; t.arg2.type = nil_a; make_operand(quad->result, &t.result); emit_instruction(&t); }
static INLINE void emit_i(struct ppc_function *p, uint op, uint li, uint aa, uint lk) { union i_inst inst; inst.inst.op = op; inst.inst.li = li; inst.inst.aa = aa; inst.inst.lk = lk; emit_instruction(p, inst.bits); }
void generate_instr(enum vmopcode op,quad* quad){ struct instruction t; t.opcode = op; if(op==23){ printf("element:%lf,type:%d\n",quad->arg1->numConst,quad->arg1->type ); } make_operand(quad->arg1, &(t.arg1)); make_operand(quad->arg2, &(t.arg2)); make_operand(quad->result, &(t.result)); quad->taddress = nextinstructionlabel(); emit_instruction(&t); }
void generate_RETURN(quad* quad){ quad->taddress = nextinstructionlabel(); struct instruction t; t.opcode = assign_v; make_retvaloperand(&t.result); t.arg2.type=nil_a; make_operand(quad->arg1, &t.arg1); emit_instruction(&t); struct userfunc* f; f = functop(funcstack); f->returnList = (struct userfunc*)malloc(sizeof(struct userfunc)); append(f->returnList, nextinstructionlabel()); t.opcode = jump_v; reset_operand(&t.arg1); t.arg1.type = nil_a; reset_operand(&t.arg2); t.result.type = label_a; //printf("%d LABEL_A\n",f->returnList->address); emit_instruction(&t); }
static INLINE void emit_xl(struct ppc_function *p, uint op, uint bo, uint bi, uint bh, uint op2, uint lk) { union xl_inst inst; inst.inst.op = op; inst.inst.bo = bo; inst.inst.bi = bi; inst.inst.unused = 0x0; inst.inst.bh = bh; inst.inst.op2 = op2; inst.inst.lk = lk; emit_instruction(p, inst.bits); }
void generate_FUNCEND(quad* quad){ struct userfunc* f; f=funcpop(funcstack); patch_returns(f->returnList, nextinstructionlabel()); quad->taddress = nextinstructionlabel(); struct instruction t; t.opcode = funcexit_v; t.arg1.type = nil_a; t.arg2.type = nil_a; make_operand(quad->result, &t.result); t.result.val = f->index; patch_func_jump(quad->taddress); emit_instruction(&t); }
void generate_relational (int op,quad* quad) { struct instruction t; t.opcode = op; // printf("arg1:%d,arg2:%d\n", quad->arg1->boolConst,quad->arg2->boolConst); make_operand(quad->arg1, &t.arg1); make_operand(quad->arg2, &t.arg2); t.result.type = label_a; if (quad->label < currprocessedquad()) t.result.val = (quads+quad->label)->taddress; else add_incomplete_jump(nextinstructionlabel(), quad->label); quad->taddress = nextinstructionlabel(); emit_instruction(&t); }
static boolean ps20_input( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { struct src_register reg; SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; switch (semantic.SemanticName) { case TGSI_SEMANTIC_POSITION: /* Special case: */ reg = src_register( SVGA3DREG_MISCTYPE, SVGA3DMISCREG_POSITION ); break; case TGSI_SEMANTIC_COLOR: reg = src_register( SVGA3DREG_INPUT, semantic.SemanticIndex ); break; case TGSI_SEMANTIC_FOG: assert(semantic.SemanticIndex == 0); reg = src_register( SVGA3DREG_TEXTURE, 0 ); break; case TGSI_SEMANTIC_GENERIC: reg = src_register( SVGA3DREG_TEXTURE, semantic.SemanticIndex + 1 ); break; default: assert(0); return TRUE; } emit->input_map[idx] = reg; dcl.dst = dst( reg ); dcl.usage = 0; dcl.index = 0; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
static INLINE void emit_va(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, uint vC, const char *format) { union va_inst inst; inst.inst.op = 4; inst.inst.vD = vD; inst.inst.vA = vA; inst.inst.vB = vB; inst.inst.vC = vC; inst.inst.op2 = op2; emit_instruction(p, inst.bits); if (p->print) { indent(p); printf(format, vD, vA, vB, vC); } }
static INLINE void emit_x(struct ppc_function *p, uint op, uint vrs, uint ra, uint rb, uint op2, const char *format) { union x_inst inst; inst.inst.op = op; inst.inst.vrs = vrs; inst.inst.ra = ra; inst.inst.rb = rb; inst.inst.op2 = op2; inst.inst.unused = 0x0; emit_instruction(p, inst.bits); if (p->print) { indent(p); printf(format, vrs, ra, rb); } }
static boolean ps20_sampler( struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx ) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx ); dcl.type = svga_tgsi_sampler_type( emit, idx ); return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
static INLINE void emit_a(struct ppc_function *p, uint op, uint frt, uint fra, uint frb, uint op2, uint rc, const char *format) { union a_inst inst; inst.inst.op = op; inst.inst.frt = frt; inst.inst.fra = fra; inst.inst.frb = frb; inst.inst.unused = 0x0; inst.inst.op2 = op2; inst.inst.rc = rc; emit_instruction(p, inst.bits); if (p->print) { indent(p); printf(format, frt, fra, frb); } }
static INLINE void emit_xo(struct ppc_function *p, uint op, uint rt, uint ra, uint rb, uint oe, uint op2, uint rc, const char *format) { union xo_inst inst; inst.inst.op = op; inst.inst.rt = rt; inst.inst.ra = ra; inst.inst.rb = rb; inst.inst.oe = oe; inst.inst.op2 = op2; inst.inst.rc = rc; emit_instruction(p, inst.bits); if (p->print) { indent(p); printf(format, rt, ra, rb); } }
/** * Declare a VS input register. * We still make up the input semantics the same as in 2.0 */ static boolean vs30_input(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; unsigned usage, index; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; if (emit->key.vkey.zero_stride_vertex_elements & (1 << idx)) { unsigned i; unsigned offset = 0; unsigned start_idx = emit->info.file_max[TGSI_FILE_CONSTANT] + 1; /* adjust for prescale constants */ start_idx += emit->key.vkey.need_prescale ? 2 : 0; /* compute the offset from the start of zero stride constants */ for (i = 0; i < PIPE_MAX_ATTRIBS && i < idx; ++i) { if (emit->key.vkey.zero_stride_vertex_elements & (1<<i)) ++offset; } emit->input_map[idx] = src_register( SVGA3DREG_CONST, start_idx + offset ); } else { emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); assert(dcl.dst.reserved0); svga_generate_vdecl_semantics( idx, &usage, &index ); dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); } return TRUE; }
static INLINE void emit_vx(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, const char *format, boolean transpose) { union vx_inst inst; inst.inst.op = 4; inst.inst.vD = vD; inst.inst.vA = vA; inst.inst.vB = vB; inst.inst.op2 = op2; emit_instruction(p, inst.bits); if (p->print) { indent(p); if (transpose) printf(format, vD, vB, vA); else printf(format, vD, vA, vB); } }
static INLINE void emit_d(struct ppc_function *p, uint op, uint rt, uint ra, int si, const char *format, boolean transpose) { union d_inst inst; assert(si >= -32768); assert(si <= 32767); inst.inst.op = op; inst.inst.rt = rt; inst.inst.ra = ra; inst.inst.si = (unsigned) (si & 0xffff); emit_instruction(p, inst.bits); if (p->print) { indent(p); if (transpose) printf(format, rt, si, ra); else printf(format, rt, ra, si); } }
void NativeGenerator::generate_native_string_entries() { comment_section("Native entry points for string functions"); { //--------------------java.lang.String.indexof0--------------------------- rom_linkable_entry("native_string_indexof0_entry"); wtk_profile_quick_call(/* param_size*/ 2); comment("Pop the return address"); popl(edi); comment("Push zero for fromIndex"); pushl(Constant(0)); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_indexof_entry")); rom_linkable_entry_end(); // native_string_indexof0_entry //--------------------java.lang.String.indexof--------------------------- rom_linkable_entry("native_string_indexof_entry"); Label cont, loop, test, failure, success; wtk_profile_quick_call(/* param_size*/ 3); comment("Pop the return address"); popl(edi); comment("Pop the argument: fromIndex"); pop_int(eax, eax); comment("Pop the argument: ch"); pop_int(ebx, ebx); comment("Pop the receiver"); pop_obj(ecx, ecx); cmpl(ebx, Constant(0xFFFF)); jcc(greater, Constant(failure)); cmpl(eax, Constant(0)); jcc(greater_equal, Constant(cont)); movl(eax, Constant(0)); bind(cont); movl(esi, Address(ecx, Constant(String::count_offset()))); comment("if (fromIndex >= count) { return -1; }"); cmpl(eax, esi); jcc(greater_equal, Constant(failure)); movl(edx, Address(ecx, Constant(String::offset_offset()))); addl(eax, edx); // i = offset + fromIndex addl(edx, esi); // int max = offset + count; movl(esi, Address(ecx, Constant(String::value_offset()))); // v = value. jmp(Constant(test)); bind(loop); cmpw(Address(esi, eax, times_2, Constant(Array::base_offset())), ebx); jcc(equal, Constant(success)); incl(eax); bind(test); cmpl(eax, edx); jcc(less, Constant(loop)); comment("Return -1 by pushing the value and jumping to the return address"); bind(failure); push_int(-1); jmp(edi); comment("Return i - offset by pushing the value and jumping to the return address"); bind(success); movl(esi, Address(ecx, Constant(String::offset_offset()))); // i = offset + fromIndex subl(eax, esi); push_int(eax); jmp(edi); rom_linkable_entry_end(); // native_string_indexof_entry } //----------------------java.lang.String.charAt--------------------------- { rom_linkable_entry("native_string_charAt_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String(java.lang.StringBuffer)------------- { rom_linkable_entry("native_string_init_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.equals(java.lang.Object)------------ { rom_linkable_entry("native_string_equals_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.indexOf(java.lang.String)----------- { rom_linkable_entry("native_string_indexof0_string_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.indexOf(java.lang.String)----------- { rom_linkable_entry("native_string_indexof_string_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.compareTo--------------------------- { // java.lang.String.compareTo // Method int compareTo(java.lang.String) rom_linkable_entry("native_string_compareTo_entry"); wtk_profile_quick_call(/* param_size*/ 2); comment("preserve method"); pushl(ebx); // 8 is return address plus pushed method int str1_offset = JavaFrame::arg_offset_from_sp(0) + 8, str0_offset = JavaFrame::arg_offset_from_sp(1) + 8; comment("load arguments to registers"); movl(ecx, Address(esp, Constant(str1_offset))); movl(eax, Address(esp, Constant(str0_offset))); // eax: str0: this String // ebx: str1: String to compare against Label bailout; comment("Null check"); testl(ecx, ecx); jcc(zero, Constant(bailout)); comment("get str0.value[]"); movl(esi, Address(eax, Constant(String::value_offset()))); comment("get str0.offset"); movl(ebx, Address(eax, Constant(String::offset_offset()))); comment("compute start of character data"); leal(esi, Address(esi, ebx, times_2, Constant(Array::base_offset()))); comment("get str0.count"); movl(eax, Address(eax, Constant(String::count_offset()))); comment("get str1.value[]"); movl(edi, Address(ecx, Constant(String::value_offset()))); comment("get str1.offset"); movl(ebx, Address(ecx, Constant(String::offset_offset()))); comment("compute start of character data"); leal(edi, Address(edi, ebx, times_2, Constant(Array::base_offset()))); comment("get str1.count"); movl(ebx, Address(ecx, Constant(String::count_offset()))); // esi = str0 start of character data // edi = str1 start of character data // eax = str0 length // ebx = str1 length Label str1_longest; subl(eax, ebx); jcc(greater_equal, Constant(str1_longest)); // str1 is longer than str0 addl(ebx, eax); bind(str1_longest); // esi = str0 start of character data // edi = str1 start of character data // eax = str0.count - str1.count // ebx = min(str0.count, str1.count) // save str0.count - str1.count, we might need it later pushl(eax); xorl(ecx, ecx); Label loop, check_lengths, done; bind(loop); cmpl(ecx, ebx); jcc(above_equal, Constant(check_lengths)); movzxw(eax, Address(esi, ecx, times_2)); movzxw(edx, Address(edi, ecx, times_2)); subl(eax, edx); jcc(not_equal, Constant(done)); incl(ecx); jmp(Constant(loop)); bind(check_lengths); movl(eax, Address(esp)); bind(done); popl(ebx); // remove saved length difference // Push result on stack and return to caller popl(ebx); // remove method popl(edi); // pop return address addl(esp, Constant(2 * BytesPerStackElement)); // remove arguments push_int(eax); // push result jmp(edi); // return comment("Bail out to the general compareTo implementation"); bind(bailout); comment("pop method"); popl(ebx); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_compareTo_entry } //----------------------java.lang.String.endsWith---------------- { // java.lang.String.endsWith // Method boolean endsWith(java.lang.String) rom_linkable_entry("native_string_endsWith_entry"); wtk_profile_quick_call(/* param_size*/ 2); Label bailout; // 4 is return address int suffix_offset = JavaFrame::arg_offset_from_sp(0) + 4, this_offset = JavaFrame::arg_offset_from_sp(1) + 4; comment("load arguments to registers"); movl(eax, Address(esp, Constant(suffix_offset))); cmpl(eax, Constant(0)); jcc(equal, Constant(bailout)); movl(ecx, Address(esp, Constant(this_offset))); comment("Pop the return address"); popl(edi); movl(edx, Address(ecx, Constant(String::count_offset()))); subl(edx, Address(eax, Constant(String::count_offset()))); comment("Push (this.count - suffix.count) for toffset"); pushl(edx); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_startsWith_entry")); comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_endsWith_entry } //----------------------java.lang.String.startsWith---------------- { // java.lang.String.startsWith // Method boolean startsWith(java.lang.String) rom_linkable_entry("native_string_startsWith0_entry"); wtk_profile_quick_call(/* param_size*/ 2); Label bailout; // 4 is return address int prefix_offset = JavaFrame::arg_offset_from_sp(0) + 4; comment("Check if prefix is null"); cmpl(Address(esp, Constant(prefix_offset)), Constant(0)); jcc(equal, Constant(bailout)); comment("Pop the return address"); popl(edi); comment("Push zero for toffset"); pushl(Constant(0)); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_startsWith_entry")); comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_startsWith0_entry } { // ----------- java.lang.String.startsWith ------------------------------ // Method boolean startsWith(java.lang.String,int) rom_linkable_entry("native_string_startsWith_entry"); wtk_profile_quick_call(/* param_size*/ 3); Label bailout, return_false; // 4 is return address int prefix_offset = JavaFrame::arg_offset_from_sp(1) + 4; comment("Check if prefix is null"); cmpl(Address(esp, Constant(prefix_offset)), Constant(0)); jcc(equal, Constant(bailout)); comment("Pop the return address"); popl(edi); comment("Pop the argument: toffset"); pop_int(edx, edx); comment("Pop the argument: prefix"); pop_obj(eax, eax); comment("Pop the receiver"); pop_obj(ecx, ecx); comment("Preserve the return address"); pushl(edi); // ecx: this String // eax: prefix cmpl(edx, Constant(0)); jcc(less, Constant(return_false)); comment("if (toffset > this.count - prefix.count) return false;"); movl(ebx, Address(ecx, Constant(String::count_offset()))); subl(ebx, Address(eax, Constant(String::count_offset()))); cmpl(edx, ebx); jcc(greater, Constant(return_false)); comment("get this.value[]"); movl(esi, Address(ecx, Constant(String::value_offset()))); comment("get this.offset"); movl(ebx, Address(ecx, Constant(String::offset_offset()))); comment("add toffset"); addl(ebx, edx); comment("compute start of character data"); leal(esi, Address(esi, ebx, times_2, Constant(Array::base_offset()))); comment("get prefix.value[]"); movl(edi, Address(eax, Constant(String::value_offset()))); comment("get prefix.offset"); movl(ebx, Address(eax, Constant(String::offset_offset()))); comment("compute start of character data"); leal(edi, Address(edi, ebx, times_2, Constant(Array::base_offset()))); comment("get prefix.count"); movl(ecx, Address(eax, Constant(String::count_offset()))); comment("get the number of bytes to compare"); shll(ecx, Constant(1)); comment("memcmp(edi, esi, ecx);"); pushl(ecx); pushl(esi); pushl(edi); if (GenerateInlineAsm) { // VC++ treats memcmp() as an intrinsic function and would cause // reference to memcmp in Interpreter_i386.c to fail to compile. call(Constant("memcmp_from_interpreter")); } else { call(Constant("memcmp")); } addl(esp, Constant(12)); cmpl(eax, Constant(0)); jcc(not_equal, Constant(return_false)); // Push 1 on stack and return to caller popl(edi); // pop return address push_int(1); // push result jmp(edi); // return bind(return_false); // Push 0 on stack and return to caller popl(edi); // pop return address push_int(0); // push result jmp(edi); // return comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_startsWith_entry } }
void generate_NOP () { struct instruction t; t.opcode=nop_v; emit_instruction(&t); }
void lp_build_tgsi_aos(LLVMBuilderRef builder, const struct tgsi_token *tokens, struct lp_type type, const unsigned char swizzles[4], LLVMValueRef consts_ptr, const LLVMValueRef *inputs, LLVMValueRef *outputs, struct lp_build_sampler_aos *sampler, const struct tgsi_shader_info *info) { struct lp_build_tgsi_aos_context bld; struct tgsi_parse_context parse; uint num_immediates = 0; uint num_instructions = 0; unsigned chan; int pc = 0; /* Setup build context */ memset(&bld, 0, sizeof bld); lp_build_context_init(&bld.base, builder, type); lp_build_context_init(&bld.int_bld, builder, lp_int_type(type)); for (chan = 0; chan < 4; ++chan) { bld.swizzles[chan] = swizzles[chan]; bld.inv_swizzles[swizzles[chan]] = chan; } bld.inputs = inputs; bld.outputs = outputs; bld.consts_ptr = consts_ptr; bld.sampler = sampler; bld.indirect_files = info->indirect_files; bld.instructions = (struct tgsi_full_instruction *) MALLOC(LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction)); bld.max_instructions = LP_MAX_INSTRUCTIONS; if (!bld.instructions) { return; } tgsi_parse_init(&parse, tokens); while (!tgsi_parse_end_of_tokens(&parse)) { tgsi_parse_token(&parse); switch(parse.FullToken.Token.Type) { case TGSI_TOKEN_TYPE_DECLARATION: /* Inputs already interpolated */ emit_declaration(&bld, &parse.FullToken.FullDeclaration); break; case TGSI_TOKEN_TYPE_INSTRUCTION: { /* save expanded instruction */ if (num_instructions == bld.max_instructions) { struct tgsi_full_instruction *instructions; instructions = REALLOC(bld.instructions, bld.max_instructions * sizeof(struct tgsi_full_instruction), (bld.max_instructions + LP_MAX_INSTRUCTIONS) * sizeof(struct tgsi_full_instruction)); if (!instructions) { break; } bld.instructions = instructions; bld.max_instructions += LP_MAX_INSTRUCTIONS; } memcpy(bld.instructions + num_instructions, &parse.FullToken.FullInstruction, sizeof(bld.instructions[0])); num_instructions++; } break; case TGSI_TOKEN_TYPE_IMMEDIATE: /* simply copy the immediate values into the next immediates[] slot */ { const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; float imm[4]; assert(size <= 4); assert(num_immediates < LP_MAX_TGSI_IMMEDIATES); for (chan = 0; chan < 4; ++chan) { imm[chan] = 0.0f; } for (chan = 0; chan < size; ++chan) { unsigned swizzle = bld.swizzles[chan]; imm[swizzle] = parse.FullToken.FullImmediate.u[chan].Float; } bld.immediates[num_immediates] = lp_build_const_aos(type, imm[0], imm[1], imm[2], imm[3], NULL); num_immediates++; } break; case TGSI_TOKEN_TYPE_PROPERTY: break; default: assert(0); } } while (pc != -1) { struct tgsi_full_instruction *instr = bld.instructions + pc; const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(instr->Instruction.Opcode); if (!emit_instruction(&bld, instr, opcode_info, &pc)) _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n", opcode_info->mnemonic); } if (0) { LLVMBasicBlockRef block = LLVMGetInsertBlock(builder); LLVMValueRef function = LLVMGetBasicBlockParent(block); debug_printf("11111111111111111111111111111 \n"); tgsi_dump(tokens, 0); lp_debug_dump_value(function); debug_printf("2222222222222222222222222222 \n"); } tgsi_parse_free(&parse); if (0) { LLVMModuleRef module = LLVMGetGlobalParent( LLVMGetBasicBlockParent(LLVMGetInsertBlock(bld.base.builder))); LLVMDumpModule(module); } FREE(bld.instructions); }
/** * Declare a VS output. * VS3.0 outputs have proper declarations and semantic info for * matching against PS inputs. */ static boolean vs30_output(struct svga_shader_emitter *emit, struct tgsi_declaration_semantic semantic, unsigned idx) { SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; unsigned usage, index; opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->vs30_output_count >= SVGA3D_OUTPUTREG_MAX) return FALSE; dcl.dst = dst_register( SVGA3DREG_OUTPUT, emit->vs30_output_count++ ); dcl.usage = usage; dcl.index = index; dcl.values[0] |= 1<<31; if (semantic.Name == TGSI_SEMANTIC_POSITION) { assert(idx == 0); emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_pos = emit->output_map[idx]; emit->true_pos = dcl.dst; /* Grab an extra output for the depth output */ if (!vs30_output_emit_depth_fog( emit, &emit->depth_pos )) return FALSE; } else if (semantic.Name == TGSI_SEMANTIC_PSIZE) { emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); emit->temp_psiz = emit->output_map[idx]; /* This has the effect of not declaring psiz (below) and not * emitting the final MOV to true_psiz in the postamble. */ if (!emit->key.vs.allow_psiz) return TRUE; emit->true_psiz = dcl.dst; } else if (semantic.Name == TGSI_SEMANTIC_FOG) { /* * Fog is shared with depth. * So we need to decrement out_count since emit_depth_fog will increment it. */ emit->vs30_output_count--; if (!vs30_output_emit_depth_fog( emit, &emit->output_map[idx] )) return FALSE; return TRUE; } else { emit->output_map[idx] = dcl.dst; } return (emit_instruction(emit, opcode) && svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); }
void NativeGenerator::generate_native_system_entries() { comment_section("Native entry points for system functions"); rom_linkable_entry("native_jvm_unchecked_byte_arraycopy_entry"); jmp(Constant("native_system_arraycopy_entry")); rom_linkable_entry_end(); rom_linkable_entry("native_jvm_unchecked_char_arraycopy_entry"); jmp(Constant("native_system_arraycopy_entry")); rom_linkable_entry_end(); rom_linkable_entry("native_jvm_unchecked_int_arraycopy_entry"); jmp(Constant("native_system_arraycopy_entry")); rom_linkable_entry_end(); rom_linkable_entry("native_jvm_unchecked_long_arraycopy_entry"); jmp(Constant("native_system_arraycopy_entry")); rom_linkable_entry_end(); rom_linkable_entry("native_jvm_unchecked_obj_arraycopy_entry"); jmp(Constant("native_system_arraycopy_entry")); rom_linkable_entry_end(); rom_linkable_entry("native_system_arraycopy_entry"); wtk_profile_quick_call(/* param_size*/ 5); Label bailout, cont, try_2_byte, try_4_byte, try_8_byte, do_4_byte; // public static native void arraycopy(Object src, int src_position, // Object dst, int dst_position, // int length); comment("preserve method"); pushl(ebx); // 8 is for the preserved method and the return address int length_offset = JavaFrame::arg_offset_from_sp(0) + 8, dst_pos_offset = JavaFrame::arg_offset_from_sp(1) + 8, dst_offset = JavaFrame::arg_offset_from_sp(2) + 8, src_pos_offset = JavaFrame::arg_offset_from_sp(3) + 8, src_offset = JavaFrame::arg_offset_from_sp(4) + 8; comment("load arguments to registers"); movl(ecx, Address(esp, Constant(length_offset))); movl(edi, Address(esp, Constant(dst_pos_offset))); movl(edx, Address(esp, Constant(dst_offset))); movl(esi, Address(esp, Constant(src_pos_offset))); movl(eax, Address(esp, Constant(src_offset))); // eax = src // ebx = tmp register // edx = dst // ecx = length // esi = src_pos // edi = dst_pos comment("if (src == NULL) goto bailout;"); testl( eax, eax ); jcc(zero, Constant(bailout)); comment("if (dst == NULL) goto bailout;"); testl( edx, edx ); jcc(zero, Constant(bailout)); comment("if (length < 0 || src_pos < 0 || dst_pos < 0) goto bailout;"); movl(ebx, ecx); orl(ebx, esi); orl(ebx, edi); jcc(negative, Constant(bailout)); comment("if ((unsigned int) dst.length < (unsigned int) dst_pos + (unsigned int) length) goto bailout;"); movl(ebx, ecx); addl(ebx, edi); cmpl(Address(edx, Constant(Array::length_offset())), ebx); jcc(below, Constant(bailout)); comment("if ((unsigned int) src.length < (unsigned int) src_pos + (unsigned int) length) goto bailout;"); movl(ebx, ecx); addl(ebx, esi); cmpl(Address(eax, Constant(Array::length_offset())), ebx); jcc(below, Constant(bailout)); comment("Same near test"); comment("if (src.near != dst.near) goto bailout;"); movl(ebx, Address(eax, Constant(Oop::klass_offset()))); cmpl(ebx, Address(edx, Constant(Oop::klass_offset()))); jcc(not_equal, Constant(bailout)); comment("load the instance_size"); movl(ebx, Address(ebx, Constant(JavaNear::klass_offset()))); movsxw(ebx, Address(ebx, Constant(FarClass::instance_size_offset()))); comment("if (instance_size != size_type_array_1()) goto try_2_byte"); cmpl(ebx, Constant(InstanceSize::size_type_array_1)); jcc(not_equal, Constant(try_2_byte)); leal(esi, Address(eax, esi, times_1, Constant(Array::base_offset()))); leal(edi, Address(edx, edi, times_1, Constant(Array::base_offset()))); jmp(Constant(cont)); bind(try_2_byte); comment("if (instance_size != size_type_array_2()) goto try_4_byte"); cmpl(ebx, Constant(InstanceSize::size_type_array_2)); jcc(not_equal, Constant(try_4_byte)); leal(esi, Address(eax, esi, times_2, Constant(Array::base_offset()))); leal(edi, Address(edx, edi, times_2, Constant(Array::base_offset()))); shll(ecx, Constant(1)); jmp(Constant(cont)); bind(try_4_byte); comment("if (instance_size == size_type_array_4()) goto do_4_byte"); cmpl(ebx, Constant(InstanceSize::size_type_array_4)); jcc(equal, Constant(do_4_byte) ); comment("if (instance_size != size_obj_array()) goto bailout"); cmpl(ebx, Constant(InstanceSize::size_obj_array)); jcc(not_equal, Constant(bailout)); comment("if (dst < old_generation_end) goto bailout"); cmpl( edx, Address( Constant( "_old_generation_end" ) ) ); jcc( below, Constant(bailout)); bind(do_4_byte); leal(esi, Address(eax, esi, times_4, Constant(Array::base_offset()))); leal(edi, Address(edx, edi, times_4, Constant(Array::base_offset()))); shll(ecx, Constant(2)); bind(cont); comment("memmove(edi, esi, ecx);"); pushl(ecx); pushl(esi); pushl(edi); call(Constant("memmove")); addl(esp, Constant(16)); ret(Constant(5 * BytesPerStackElement)); comment("Bail out to the general arraycopy implementation"); bind(bailout); comment("pop method"); popl(ebx); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_system_arraycopy_entry }
void SourceAssembler::emit_instruction(const char* format, ...) { va_list arguments; va_start(arguments, format); emit_instruction(format, arguments); va_end(arguments); }