/* * DEFW */ int op_dw(void) { register int i, len, temp; register char *p; register char *s; if (!gencode) return(0); p = operand; i = len = 0; if (pass == 1) if (*label) put_label(); while (*p) { s = tmp; while (*p != ',' && *p != '\0') *s++ = *p++; *s = '\0'; if (pass == 2) { temp = eval(tmp); ops[i++] = temp & 0xff; ops[i++] = temp >> 8; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } len += 2; if (*p == ',') p++; }
/* * Pass 1: * - process one line of source * * Output: 1 line processed * 0 EOF */ int p1_line(void) { register char *p; register int i; register struct opc *op; if ((p = fgets(line, MAXLINE, srcfp)) == NULL) return(0); c_line++; p = get_label(label, p); p = get_opcode(opcode, p); p = get_arg(operand, p); if (strcmp(opcode, ENDFILE) == 0) return(0); if (*opcode) { if ((op = search_op(opcode)) != NULL) { i = (*op->op_fun)(op->op_c1, op->op_c2); if (gencode) pc += i; } else asmerr(E_ILLOPC); } else if (*label) put_label(); return(1); }
// // Output all code and labels in the peep list. // void PeepList::flush() { static bool first = true; txtoStream* oofs; OCODE *ip; /* if (pass == 2) { if (first) { compiler.storeTables(); first = false; } oofs = new txtoStream(); oofs->open(irfile, std::ios::out | std::ios::app); currentFn->pl.storeHex(*oofs); oofs->close(); delete oofs; } */ for (ip = head; ip; ip = ip->fwd) { if (ip->opcode == op_label) put_label((int)ip->oper1, "", GetNamespace(), 'C'); else ip->store(ofs); } }
void doinit(SYM *sp) { char lbl[200]; lbl[0] = 0; if (sp->storage_class == sc_thread) { seg(tlsseg); nl(); } else if (sp->storage_class == sc_static || lastst==assign) { seg(dataseg); /* initialize into data segment */ nl(); /* start a new line in object */ } else { seg(bssseg); /* initialize into data segment */ nl(); /* start a new line in object */ } if(sp->storage_class == sc_static || sp->storage_class == sc_thread) { put_label(sp->value.i, sp->name); } else { if (sp->storage_class == sc_global) strcpy(lbl, "public "); strcat(lbl, sp->name); gen_strlab(lbl); } if( lastst != assign) { genstorage(sp->tp->size); } else { NextToken(); InitializeType(sp->tp); } endinit(); }
void dump_muldivval(void) { int tag = FALSE; if (prm_asmfile) { fprintf(outputFile,"\n"); if (muldivlink) { tag = TRUE; align(4); } while (muldivlink) { put_label(muldivlink->label); if (muldivlink->size == 0) fprintf(outputFile,"\tDD\t0%xH\n",muldivlink->value); else if (muldivlink->size == 6) fprintf(outputFile,"\tDD\t%f\n",muldivlink->floatvalue); else if (muldivlink->size == 8) fprintf(outputFile,"\tDQ\t%f\n",muldivlink->floatvalue); else fprintf(outputFile,"\tDT\t%f\n",muldivlink->floatvalue); muldivlink = muldivlink->link; } if (tag) fprintf(outputFile,"\n"); } }
/* * DEFM */ int op_dm(void) { register int i; register char *p; if (!gencode) return(0); i = 0; p = operand; if (pass == 1) if (*label) put_label(); if (*p != STRSEP) { asmerr(E_MISHYP); return(0); } p++; while (*p != STRSEP) { if (*p == '\n' || *p == '\0') { asmerr(E_MISHYP); break; } ops[i++] = *p++; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } return(i); }
PRIVATE void put_storage P1 (SYM *, sp) { SIZE al = alignment_of_type (typeof (sp)); put_bseg (al); if (is_static (sp)) { put_label (sp->value.l); } else { put_name (sp); } oprintf ("\t.space\t%ld%s", typeof (sp)->size, newline); }
/* * output all code and labels in the peep list. */ void flush_peep() { if (opt_nopeep==FALSE) opt_peep(); /* do the peephole optimizations */ while( peep_head != NULL ) { if( peep_head->opcode == op_label ) put_label((int64_t)peep_head->oper1,"",GetNamespace(),'C'); else put_ocode(peep_head); peep_head = peep_head->fwd; } }
/* * output all code and labels in the peep list. */ void flush_peep P1 (unsigned, level) { register CODE *ip; SWITCH *sw; EXPR *ep2; LABEL i; opt3 (level); /* do the peephole optimizations */ for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { if (ip->opcode == op_label) { put_label (ip->oper1->u.offset->v.l); } else put_code (ip); } peep_head = NIL_CODE; for (sw = swtables; sw; sw = sw->next) { put_kseg (alignment_of_type (tp_pointer)); put_label (sw->tablab); ep2 = mk_lcon (UNDEF_LABEL); /* generate the switch jump table as a series of 2-byte offsets * This limits the amount of code that can be generated in a * function to less then 32K. I believe that this is a reasonable * restriction. */ { EXPR *ep, *ep1; ep1 = mk_lcon (sw->beglab); ep = mk_node (en_sub, ep2, ep1, tp_void); for (i = 0; i < sw->numlabs; i++) { ep2->v.l = sw->labels[i]; put_short (ep); } } } swtables = NIL_SWITCH; }
/* * DEFS */ int op_ds(void) { register int val; if (!gencode) return(0); if (pass == 1) if (*label) put_label(); sd_val = pc; sd_flag = 3; val = eval(operand); if ((pass == 2) && !dump_flag) obj_fill(val); pc += val; return(0); }
void dumplits(void) /* * dump the string literal pool. */ { while( strtab != 0) { cseg(); nl(); put_label(strtab->label); genstring(strtab->str,strtab->type); if (strtab->type) genword(0); else genbyte(0); strtab = strtab->next; } nl(); }
void doinit(SYM *sp) { char lbl[200]; lbl[0] = 0; if (sp->storage_class == sc_thread) { seg(tlsseg); nl(); } else if (sp->storage_class == sc_static || lastst==assign) { seg(dataseg); /* initialize into data segment */ nl(); /* start a new line in object */ } else { seg(bssseg); /* initialize into data segment */ nl(); /* start a new line in object */ } if(sp->storage_class == sc_static || sp->storage_class == sc_thread) { put_label(sp->value.i, sp->name, GetNamespace(), 'D'); } else { if (sp->storage_class == sc_global) { strcpy(lbl, "public "); if (curseg==dataseg) strcat(lbl, "data "); else if (curseg==bssseg) strcat(lbl, "bss "); else if (curseg==tlsseg) strcat(lbl, "tls "); } strcat(lbl, sp->name); gen_strlab(lbl); } if( lastst != assign) { genstorage(sp->tp->size); } else { NextToken(); InitializeType(sp->tp); } endinit(); if (sp->storage_class == sc_global) fprintf(output,"\nendpublic\n"); }
/* * dump the string literal pool. */ void dumplits() { char *cp; cseg(); nl(); align(8); nl(); while( strtab != NULL) { nl(); put_label(strtab->label,strtab->str); cp = strtab->str; while(*cp) GenerateChar(*cp++); GenerateChar(0); strtab = strtab->next; } nl(); }
/* * DEFB */ int op_db(void) { register int i; register char *p; register char *s; if (!gencode) return(0); i = 0; p = operand; if (pass == 1) if (*label) put_label(); while (*p) { if (*p == STRSEP) { p++; while (*p != STRSEP) { if (*p == '\n' || *p == '\0') { asmerr(E_MISHYP); goto hyp_error; } ops[i++] = *p++; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } p++; } else { s = tmp; while (*p != ',' && *p != '\0') *s++ = *p++; *s = '\0'; ops[i++] = eval(tmp); if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } if (*p == ',') p++; } hyp_error: return(i); }
/* * dump the string literal pool. * if we are producing single copies of strings (which should therefore * be read only we put them in the text segment - else in the data segment. */ PRIVATE void put_literals P0 (void) { const CHAR *cp; size_t len; if (lang_option == LANG_KANDR) { put_dseg (alignment_of_type (tp_char)); } else { put_kseg (alignment_of_type (tp_char)); } for (; strtab != 0; strtab = strtab->next) { nl (); put_label (strtab->label); cp = strtab->str; for (len = strtab->len; len--;) put_byte ((UVAL) *cp++); put_byte (Ox0UL); } nl (); }
void doinit(SYM *sp) { static bool first = true; char lbl[200]; int algn; enum e_sg oseg; char buf[500]; std::streampos endpoint; TYP *tp; hasPointer = false; if (first) { firstPrim = true; first = false; } oseg = noseg; lbl[0] = 0; // Initialize constants into read-only data segment. Constants may be placed // in ROM along with code. if (sp->isConst) { oseg = rodataseg; } if (sp->storage_class == sc_thread) { if (sp->tp->type==bt_struct || sp->tp->type==bt_union) algn = imax(sp->tp->alignment,8); else if (sp->tp->type==bt_pointer)// && sp->tp->val_flag) algn = imax(sp->tp->GetBtp()->alignment,8); else algn = 2; seg(oseg==noseg ? tlsseg : oseg,algn); nl(); } else if (sp->storage_class == sc_static || lastst==assign) { if (sp->tp->type==bt_struct || sp->tp->type==bt_union) algn = imax(sp->tp->alignment,8); else if (sp->tp->type==bt_pointer)// && sp->tp->val_flag) algn = imax(sp->tp->GetBtp()->alignment,8); else algn = 2; seg(oseg==noseg ? dataseg : oseg,algn); /* initialize into data segment */ nl(); /* start a new line in object */ } else { if (sp->tp->type==bt_struct || sp->tp->type==bt_union) algn = imax(sp->tp->alignment,8); else if (sp->tp->type==bt_pointer)// && sp->tp->val_flag) algn = imax(sp->tp->GetBtp()->alignment,8); else algn = 2; seg(oseg==noseg ? (lastst==assign ? dataseg : bssseg) : oseg,algn); /* initialize into data segment */ nl(); /* start a new line in object */ } if (sp->storage_class == sc_static || sp->storage_class == sc_thread) { //strcpy_s(glbl, sizeof(glbl), gen_label((int)sp->value.i, (char *)sp->name->c_str(), GetNamespace(), 'D')); if (sp->tp->IsSkippable()) { patchpoint = ofs.tellp(); sprintf_s(buf, sizeof(buf), "\talign\t8\n\tdw\t$FFF0200000000001\n"); ofs.printf(buf); } sp->realname = my_strdup(put_label((int)sp->value.i, (char *)sp->name->c_str(), GetNamespace(), 'D')); strcpy_s(glbl2, sizeof(glbl2), gen_label((int)sp->value.i, (char *)sp->name->c_str(), GetNamespace(), 'D')); } else { if (sp->storage_class == sc_global) { strcpy_s(lbl, sizeof(lbl), "public "); if (curseg==dataseg) strcat_s(lbl, sizeof(lbl), "data "); else if (curseg==bssseg) strcat_s(lbl, sizeof(lbl), "bss "); else if (curseg==tlsseg) strcat_s(lbl, sizeof(lbl), "tls "); } strcat_s(lbl, sizeof(lbl), sp->name->c_str()); if (sp->tp->IsSkippable()) { patchpoint = ofs.tellp(); sprintf_s(buf, sizeof(buf), "\talign\t8\n\tdw\t$FFF0200000000001\n"); ofs.printf(buf); } strcpy_s(glbl2, sizeof(glbl2), sp->name->c_str()); gen_strlab(lbl); } if (lastst == kw_firstcall) { GenerateByte(1); return; } else if( lastst != assign) { hasPointer = sp->tp->FindPointer(); genstorage(sp->tp->size); } else { NextToken(); hasPointer = sp->tp->FindPointer(); typ_sp = 0; tp = sp->tp; push_typ(tp); while (tp = tp->GetBtp()) { push_typ(tp); } brace_level = 0; sp->tp->Initialize(nullptr); if (sp->tp->numele == 0) { if (sp->tp->GetBtp()) { if (sp->tp->GetBtp()->type == bt_char || sp->tp->GetBtp()->type == bt_uchar || sp->tp->GetBtp()->type == bt_ichar || sp->tp->GetBtp()->type == bt_iuchar ) { sp->tp->numele = laststrlen; sp->tp->size = laststrlen; } } } } if (!hasPointer && sp->tp->IsSkippable()) { endpoint = ofs.tellp(); ofs.seekp(patchpoint); sprintf_s(buf, sizeof(buf), "\talign\t8\n\tdw\t$%I64X\n", ((genst_cumulative + 7LL) >> 3LL) | 0xFFF0200000000000LL); ofs.printf(buf); ofs.seekp(endpoint); genst_cumulative = 0; }
void doinit(SYM *sp) { char lbl[200]; int algn; enum e_sg oseg; oseg = noseg; lbl[0] = 0; // Initialize constants into read-only data segment. Constants may be placed // in ROM along with code. if (sp->isConst) { oseg = rodataseg; } if (sp->storage_class == sc_thread) { if (sp->tp->type==bt_struct || sp->tp->type==bt_union) algn = imax(sp->tp->alignment,2); else if (sp->tp->type==bt_pointer && sp->tp->val_flag) algn = imax(sp->tp->GetBtp()->alignment,2); else algn = 2; seg(oseg==noseg ? tlsseg : oseg,algn); nl(); } else if (sp->storage_class == sc_static || lastst==assign) { if (sp->tp->type==bt_struct || sp->tp->type==bt_union) algn = imax(sp->tp->alignment,2); else if (sp->tp->type==bt_pointer && sp->tp->val_flag) algn = imax(sp->tp->GetBtp()->alignment,2); else algn = 2; seg(oseg==noseg ? dataseg : oseg,algn); /* initialize into data segment */ nl(); /* start a new line in object */ } else { if (sp->tp->type==bt_struct || sp->tp->type==bt_union) algn = imax(sp->tp->alignment,2); else if (sp->tp->type==bt_pointer && sp->tp->val_flag) algn = imax(sp->tp->GetBtp()->alignment,2); else algn = 2; seg(oseg==noseg ? bssseg : oseg,algn); /* initialize into data segment */ nl(); /* start a new line in object */ } if(sp->storage_class == sc_static || sp->storage_class == sc_thread) { sp->realname = my_strdup(put_label(sp->value.i, (char *)sp->name->c_str(), GetNamespace(), 'D')); } else { if (sp->storage_class == sc_global) { strcpy_s(lbl, sizeof(lbl), "public "); if (curseg==dataseg) strcat_s(lbl, sizeof(lbl), "data "); else if (curseg==bssseg) strcat_s(lbl, sizeof(lbl), "bss "); else if (curseg==tlsseg) strcat_s(lbl, sizeof(lbl), "tls "); } strcat_s(lbl, sizeof(lbl), sp->name->c_str()); gen_strlab(lbl); } if (lastst == kw_firstcall) { GenerateByte(1); return; } else if( lastst != assign) { genstorage(sp->tp->size); } else { NextToken(); InitializeType(sp->tp); } endinit(); if (sp->storage_class == sc_global) ofs.printf("\nendpublic\n"); }
void dumplits() { char *cp; int64_t nn; slit *lit; dfs.printf("<Dumplits>\n"); roseg(); if (casetab) { nl(); align(8); nl(); } while (casetab != nullptr) { nl(); if (casetab->pass == 2) put_label(casetab->label, "", casetab->nmspace, 'D'); for (nn = 0; nn < casetab->num; nn++) { if (casetab->cases[nn].pass==2) GenerateLabelReference(casetab->cases[nn].label, 0); } casetab = casetab->next; } if (quadtab) { nl(); align(8); nl(); } // Dumping to ro segment - no need for GC skip /* nn = GetQuadtabLen(); if (nn) { sprintf_s(buf, sizeof(buf), "\tdw\t$%I64X ; GC_skip\n", nn | 0xFFF0200000000000LL); ofs.printf("%s", buf); } */ while(quadtab != nullptr) { nl(); if (DataLabels[quadtab->label]) { put_label(quadtab->label, "", quadtab->nmspace, 'D'); ofs.printf("\tdh\t"); quadtab->Pack(64); ofs.printf("%s", quadtab->ToString(64)); outcol += 35; } quadtab = quadtab->next; } if (strtab) { nl(); align(8); nl(); } //nn = GetStrtabLen(); //if (nn) { // sprintf_s(buf, sizeof(buf), "\tdw\t$%I64X ; GC_skip\n", nn | 0xFFF0200000000000LL); // ofs.printf("%s", buf); //} for (lit = strtab; lit; lit = lit->next) { ENODE *ep; agr = ep = (ENODE *)lit->str; dfs.printf("."); nl(); if (!lit->isString) { if (DataLabels[lit->label]) put_label(lit->label, strip_crlf(&lit->str[1]), lit->nmspace, 'D'); } else put_label(lit->label,strip_crlf(&lit->str[1]),lit->nmspace,'D'); if (lit->isString) { cp = lit->str; switch (*cp) { case 'B': cp++; while (*cp) GenerateByte(*cp++); GenerateByte(0); break; case 'C': cp++; while (*cp) GenerateChar(*cp++); GenerateChar(0); break; case 'H': cp++; while (*cp) GenerateHalf(*cp++); GenerateHalf(0); break; case 'W': cp++; while (*cp) GenerateWord(*cp++); GenerateWord(0); break; } } else { if (DataLabels[lit->label]) { ep->PutStructConst(ofs); } } } strtab = nullptr; nl(); dfs.printf("</Dumplits>\n"); }
/* * Examines dataflow and checks if data is already in a register * when read-accesses to external ram occurs * needs multiple-passes to work */ int flow_dataflow P2 (CODE *, peep_head, int, level) { FLOWLISTENTRY *RegUsage[MAX_REG + 1]; int LabelChanges; BOOL headless; /* is true when currently no entrypoint for code was found * (after a jump before the first label is found */ REG reg; register CODE *ip; int replacecount = 0; static int totreplace = 0; #ifdef DEBUG int Round = 1; #endif /* DEBUG */ do { DPRINTF ((DEBUG_FLOW, "Dataflow, round %d...", Round++)); LabelChanges = 0; /* currently no entrypoint found */ headless = FALSE; /* clear all lists to start analysis */ clear_regusage (&(RegUsage[0])); for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { /* * invalidate all entries with references to registers * modified in this instruction */ validate_regusage (ip, &(RegUsage[0])); switch (ip->opcode) { case op_ldi_ldi: case op_ldf_ldf: /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst2->preg]), ip->dst2->preg, ip->src21, ip->type); if (is_am_register (ip->src21)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst2->preg]), RegUsage[ip->src21->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg, ip->dst2, ip->type); } /*FALLTHRU */ case op_ldi: case op_ldf: case op_ldiu: case op_ldfu: /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg, ip->src1, ip->type); if (is_am_register (ip->src1)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst->preg]), RegUsage[ip->src1->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); } break; case op_ldi_sti: case op_ldf_stf: /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg, ip->src1, ip->type); if (is_am_register (ip->src1)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst->preg]), RegUsage[ip->src1->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); } /* source of sti refers now also to destination */ add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg, ip->dst2, ip->type); break; case op_sti_sti: case op_stf_stf: /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg, ip->dst2, ip->type); /*FALLTHRU */ case op_sti: case op_stf: /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); break; case op_absf_stf: case op_absi_sti: case op_addf3_stf: case op_addi3_sti: case op_and3_sti: case op_ash3_sti: case op_fix_sti: case op_float_stf: case op_lsh3_sti: case op_mpyf3_stf: case op_mpyi3_sti: case op_negf_stf: case op_negi_sti: case op_not_sti: case op_or3_sti: case op_subf3_stf: case op_subi3_sti: case op_xor3_sti: /* source of sti refers now also to destination */ add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg, ip->dst2, ip->type); if ((ip->dst != NULL) && (is_am_register (ip->dst))) { /* destination of operation does not reference to anywhere now */ RegUsage[ip->dst->preg] = NULL; } break; case op_blo: case op_bls: case op_bhi: case op_bhs: case op_beq: case op_bne: case op_blt: case op_ble: case op_bgt: case op_bge: case op_bz: case op_bnz: case op_bp: case op_bn: case op_bnn: /* attach aktual registerusageinfo to label of jumpdestination */ LabelChanges += attach_regusage_to_label (ip, &(RegUsage[0]), level); break; case op_label: if (headless == TRUE) { /* first entrypoint of this piece of code, so use whole information from label */ copy_regusage_from_label (ip, &(RegUsage[0]), level); headless = FALSE; } else { /* not first entrypoint, so merge information from label */ LabelChanges += merge_regusage_from_label (ip, &(RegUsage[0]), level); } break; case op_bu: case op_br: /* attach aktual registerusageinfo to label of jumpdestination */ LabelChanges += attach_regusage_to_label (ip, &(RegUsage[0]), level); /* FALLTHRU */ case op_retsu: case op_retiu: /* no information abaout registers availlable now */ clear_regusage (&(RegUsage[0])); /* since no entrypoint found now (unconditional controltransfer) */ headless = TRUE; break; case op_asm: /* clear whole list, asm can do anything to registers and memory */ clear_regusage (&(RegUsage[0])); break; case op_rpts: case op_rptb: /* remove all references to and from blockrepeatregisters */ RegUsage[REG_RC] = NULL; RegUsage[REG_RS] = NULL; RegUsage[REG_RE] = NULL; remove_from_regusage (RegUsage, REG_RC); remove_from_regusage (RegUsage, REG_RS); remove_from_regusage (RegUsage, REG_RE); break; case op_call: case op_trapu: case op_xcall: case op_callu: /* remove all references to and from temporary registers */ clear_tempreg_usage (&(RegUsage[0])); /* * we do not know what called routine does * with memory */ remove_from_regusage (RegUsage, REG_MEMORY); /* FALLTHRU */ case op_push: case op_pop: case op_pushf: case op_popf: case op_pushnopeep: case op_pushfnopeep: /* references from SP are no longer valid */ RegUsage[REG_SP] = NULL; /* FALLTHRU */ default: if ((ip->dst != NULL) && (is_am_register (ip->dst))) { /* destination of operation does not reference to anywhere now */ RegUsage[ip->dst->preg] = NULL; } if ((ip->dst2 != NULL) && (is_am_register (ip->dst2))) { /* destination of operation does not reference to anywhere now */ RegUsage[ip->dst2->preg] = NULL; } break; } } DPRINTF ((DEBUG_FLOW, " %d changes \n", LabelChanges)); } while (LabelChanges != 0); DPRINTF ((DEBUG_FLOW, "%s\n", "Dataflow, REPLACEMENT ROUND")); LabelChanges = 0; /* currently no entrypoint found */ headless = FALSE; /* clear all lists to start analysis */ clear_regusage (&(RegUsage[0])); for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { /* * invalidate all entries with references to registers * modified in this instruction */ #ifdef ENHANCED_FLOW validate_addressregusage (ip, &(RegUsage[0])); #else validate_regusage (ip, &(RegUsage[0])); #endif switch (ip->opcode) { case op_ldi_ldi: case op_ldf_ldf: if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src21, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src21 %d", (int) reg)); if (is_exchangable (&(ip->src21), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg, ip->src1, ip->type); if (is_am_register (ip->src1)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst->preg]), RegUsage[ip->src1->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); } /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst2->preg]), ip->dst2->preg, ip->src21, ip->type); if (is_am_register (ip->src21)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst2->preg]), RegUsage[ip->src21->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg, ip->dst2, ip->type); } break; case op_ldi: case op_ldf: case op_ldiu: case op_ldfu: if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg, ip->src1, ip->type); if (is_am_register (ip->src1)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst->preg]), RegUsage[ip->src1->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); } break; case op_ldi_sti: case op_ldf_stf: if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src21, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src21 %d", (int) reg)); if (is_exchangable (&(ip->src21), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* destination now references to source */ new_flow_list (&(RegUsage[ip->dst->preg]), ip->dst->preg, ip->src1, ip->type); if (is_am_register (ip->src1)) { /* dest references now to the same list of values as source */ add_list_to_flow_list (&(RegUsage[ip->dst->preg]), RegUsage[ip->src1->preg]); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); } /* source of sti refers now also to destination */ add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg, ip->dst2, ip->type); break; case op_sti_sti: case op_stf_stf: #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src2->preg]), ip->src2->preg, ip->dst2, ip->type); /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); break; case op_sti: case op_stf: #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* source refers now also to destination */ add_flow_list (&(RegUsage[ip->src1->preg]), ip->src1->preg, ip->dst, ip->type); break; case op_absf_stf: case op_absi_sti: case op_addf3_stf: case op_addi3_sti: case op_and3_sti: case op_ash3_sti: case op_fix_sti: case op_float_stf: case op_lsh3_sti: case op_mpyf3_stf: case op_mpyi3_sti: case op_negf_stf: case op_negi_sti: case op_not_sti: case op_or3_sti: case op_subf3_stf: case op_subi3_sti: case op_xor3_sti: #if 0 /* * sorry, currently no replace possible, since * src1 must be r0-r7 * src2 must be restricted indirect * src21 must be r0-r7 */ if (ip->src1 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } if (ip->src2 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src2, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src2 %d", reg)); if (is_exchangable (&(ip->src2), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } #endif #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* source of sti refers now also to destination */ add_flow_list (&(RegUsage[ip->src21->preg]), ip->src21->preg, ip->dst2, ip->type); if ((ip->dst != NULL) && (is_am_register (ip->dst))) { /* destination of operation does not reference to anywhere now */ RegUsage[ip->dst->preg] = NULL; } break; case op_label: if (headless == TRUE) { /* first entrypoint of this piece of code, so use whole information from label */ copy_regusage_from_label (ip, &(RegUsage[0]), level); headless = FALSE; } else { /* not first entrypoint, so merge information from label */ LabelChanges += merge_regusage_from_label (ip, &(RegUsage[0]), level); } /* * Remove regusage-entry from label */ ip->src21 = NULL; break; case op_bu: if ((ip->src1 != NULL) && (ip->src1->mode != am_immed)) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } /* FALLTHRU */ case op_br: /* FALLTHRU */ case op_retsu: case op_retiu: #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* no information abaout registers availlable now */ clear_regusage (&(RegUsage[0])); /* since no entrypoint found now (unconditional controltransfer) */ headless = TRUE; break; case op_asm: /* clear whole list, asm can do anything to registers and memory */ clear_regusage (&(RegUsage[0])); break; case op_rpts: if (ip->src1 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } /* FALLTHRU */ case op_rptb: #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* remove all references to and from blockrepeatregisters */ RegUsage[REG_RC] = NULL; RegUsage[REG_RS] = NULL; RegUsage[REG_RE] = NULL; remove_from_regusage (RegUsage, REG_RC); remove_from_regusage (RegUsage, REG_RS); remove_from_regusage (RegUsage, REG_RE); break; case op_callu: if ((ip->src1 != NULL) && (ip->src1->mode != am_immed)) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } /* FALLTHRU */ case op_call: case op_trapu: case op_xcall: #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif /* remove all references to and from temporary registers */ clear_tempreg_usage (&(RegUsage[0])); /* * we do not know what called routine does * with memory */ remove_from_regusage (RegUsage, REG_MEMORY); /* FALLTHRU */ case op_push: case op_pop: case op_pushf: case op_popf: case op_pushnopeep: case op_pushfnopeep: /* references from SP are no longer valid */ RegUsage[REG_SP] = NULL; /* FALLTHRU */ default: if (ip->src1 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src1, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src1 %d", (int) reg)); if (is_exchangable (&(ip->src1), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } if (ip->src2 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src2, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src2 %d", (int) reg)); if (is_exchangable (&(ip->src2), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } if (ip->src21 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src21, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src21 %d", (int) reg)); if (is_exchangable (&(ip->src21), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } if (ip->src22 != NULL) { if ( (reg = search_in_regusage (&(RegUsage[0]), ip->src22, ip->type)) >= 0) { DPRINTF ( (DEBUG_FLOW, "FoundReplacement for src22 %d", (int) reg)); if (is_exchangable (&(ip->src22), reg)) { replacecount++; totreplace++; Update_Peep_Info (ip); } } } #ifdef USE_ALL_OPCODES /* FALLTHRU */ /* do no replacements with parallel mul/add */ case op_mpf3_adf3: case op_mpf3_sbf3: case op_mpi3_adi3: case op_mpi3_sbi3: #endif /* USE_ALL_OPCODES */ #ifdef ENHANCED_FLOW validate_regusage (ip, &(RegUsage[0])); #endif if ((ip->dst != NULL) && (is_am_register (ip->dst))) { /* destination of operation does not reference to anywhere now */ RegUsage[ip->dst->preg] = NULL; } if ((ip->dst2 != NULL) && (is_am_register (ip->dst2))) { /* destination of operation does not reference to anywhere now */ RegUsage[ip->dst2->preg] = NULL; } break; } #ifdef DEBUG if (is_debugging (DEBUG_FLOW)) { FHANDLE save = output; output = debugfile; if (ip->opcode == op_label) { put_label (ip->src1->u.offset->v.l); } else { put_code (ip); } output = save; print_regusage (&(RegUsage[0])); } #endif /* DEBUG */ } DPRINTF ((DEBUG_FLOW, "Replaced %d ", replacecount)); DPRINTF ((DEBUG_FLOW, "Total %d \n", totreplace)); return replacecount; }