diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/tl/l.h | 7 | ||||
| -rw-r--r-- | utils/tl/noop.c | 227 | ||||
| -rw-r--r-- | utils/tl/obj.c | 3 | ||||
| -rw-r--r-- | utils/tl/pass.c | 4 | ||||
| -rw-r--r-- | utils/tl/thumb.c | 108 |
5 files changed, 102 insertions, 247 deletions
diff --git a/utils/tl/l.h b/utils/tl/l.h index 72e6ed28..f2e6ad02 100644 --- a/utils/tl/l.h +++ b/utils/tl/l.h @@ -322,12 +322,6 @@ void addpool(Prog*, Adr*); EXTERN Prog* blitrl; EXTERN Prog* elitrl; -void initdiv(void); -EXTERN Prog* prog_div; -EXTERN Prog* prog_divu; -EXTERN Prog* prog_mod; -EXTERN Prog* prog_modu; - #pragma varargck type "A" int #pragma varargck type "C" int #pragma varargck type "D" Adr* @@ -365,7 +359,6 @@ int compound(Prog*); double cputime(void); void datblk(long, long, int); void diag(char*, ...); -void divsig(void); void dodata(void); void doprof1(void); void doprof2(void); diff --git a/utils/tl/noop.c b/utils/tl/noop.c index 08ef6dbe..d849923c 100644 --- a/utils/tl/noop.c +++ b/utils/tl/noop.c @@ -125,18 +125,6 @@ noops(void) curbecome = p->from.offset; break; - case ADIV: - case ADIVU: - case AMOD: - case AMODU: - q = p; - if(prog_div == P) - initdiv(); - if(curtext != P) - curtext->mark &= ~LEAF; - setdiv(p->as); - continue; - case ANOP: q1 = p->link; q->link = q1; /* q is non-nop */ @@ -528,122 +516,6 @@ noops(void) break; - case ADIV: - case ADIVU: - case AMOD: - case AMODU: - if(debug['M']) - break; - if(p->from.type != D_REG) - break; - if(p->to.type != D_REG) - break; - q1 = p; - - /* MOV a,4(SP) */ - q = prg(); - q->link = p->link; - p->link = q; - p = q; - - p->as = AMOVW; - p->line = q1->line; - p->from.type = D_REG; - p->from.reg = q1->from.reg; - p->to.type = D_OREG; - p->to.reg = REGSP; - p->to.offset = 4; - - /* MOV b,REGTMP */ - q = prg(); - q->link = p->link; - p->link = q; - p = q; - - p->as = AMOVW; - p->line = q1->line; - p->from.type = D_REG; - p->from.reg = q1->reg; - if(q1->reg == NREG) - p->from.reg = q1->to.reg; - p->to.type = D_REG; - p->to.reg = prog_div != UP && prog_div->from.sym->thumb ? REGTMPT : REGTMP; - p->to.offset = 0; - - /* CALL appropriate */ - q = prg(); - q->link = p->link; - p->link = q; - p = q; - -#ifdef CALLEEBX - p->as = ABL; -#else - if(prog_div != UP && prog_div->from.sym->thumb) - p->as = thumb ? ABL : ABX; - else - p->as = thumb ? ABX : ABL; -#endif - p->line = q1->line; - p->to.type = D_BRANCH; - p->cond = p; - switch(o) { - case ADIV: - p->cond = prog_div; - p->to.sym = sym_div; - break; - case ADIVU: - p->cond = prog_divu; - p->to.sym = sym_divu; - break; - case AMOD: - p->cond = prog_mod; - p->to.sym = sym_mod; - break; - case AMODU: - p->cond = prog_modu; - p->to.sym = sym_modu; - break; - } - - /* MOV REGTMP, b */ - q = prg(); - q->link = p->link; - p->link = q; - p = q; - - p->as = AMOVW; - p->line = q1->line; - p->from.type = D_REG; - p->from.reg = prog_div != UP && prog_div->from.sym->thumb ? REGTMPT : REGTMP; - p->from.offset = 0; - p->to.type = D_REG; - p->to.reg = q1->to.reg; - - /* ADD $8,SP */ - q = prg(); - q->link = p->link; - p->link = q; - p = q; - - p->as = AADD; - p->from.type = D_CONST; - p->from.reg = NREG; - p->from.offset = 8; - p->reg = NREG; - p->to.type = D_REG; - p->to.reg = REGSP; - - /* SUB $8,SP */ - q1->as = ASUB; - q1->from.type = D_CONST; - q1->from.offset = 8; - q1->from.reg = NREG; - q1->reg = NREG; - q1->to.type = D_REG; - q1->to.reg = REGSP; - - break; case AMOVW: if(thumb){ Adr *a = &p->from; @@ -786,105 +658,6 @@ noops(void) } } -static void -sigdiv(char *n) -{ - Sym *s; - - s = lookup(n, 0); - if(s->type == STEXT){ - if(s->sig == 0) - s->sig = SIGNINTERN; - } - else if(s->type == 0 || s->type == SXREF) - s->type = SUNDEF; -} - -void -divsig(void) -{ - sigdiv("_div"); - sigdiv("_divu"); - sigdiv("_mod"); - sigdiv("_modu"); -} - -static void -sdiv(Sym *s) -{ - if(s->type == 0 || s->type == SXREF){ - /* undefsym(s); */ - s->type = SXREF; - if(s->sig == 0) - s->sig = SIGNINTERN; - s->subtype = SIMPORT; - } - else if(s->type != STEXT) - diag("undefined: %s", s->name); -} - -void -initdiv(void) -{ - Sym *s2, *s3, *s4, *s5; - Prog *p; - - if(prog_div != P) - return; - sym_div = s2 = lookup("_div", 0); - sym_divu = s3 = lookup("_divu", 0); - sym_mod = s4 = lookup("_mod", 0); - sym_modu = s5 = lookup("_modu", 0); - if(dlm) { - sdiv(s2); if(s2->type == SXREF) prog_div = UP; - sdiv(s3); if(s3->type == SXREF) prog_divu = UP; - sdiv(s4); if(s4->type == SXREF) prog_mod = UP; - sdiv(s5); if(s5->type == SXREF) prog_modu = UP; - } - for(p = firstp; p != P; p = p->link) - if(p->as == ATEXT) { - if(p->from.sym == s2) - prog_div = p; - if(p->from.sym == s3) - prog_divu = p; - if(p->from.sym == s4) - prog_mod = p; - if(p->from.sym == s5) - prog_modu = p; - } - if(prog_div == P) { - diag("undefined: %s", s2->name); - prog_div = curtext; - } - if(prog_divu == P) { - diag("undefined: %s", s3->name); - prog_divu = curtext; - } - if(prog_mod == P) { - diag("undefined: %s", s4->name); - prog_mod = curtext; - } - if(prog_modu == P) { - diag("undefined: %s", s5->name); - prog_modu = curtext; - } -} - -static void -setdiv(int as) -{ - Prog *p = nil; - - switch(as){ - case ADIV: p = prog_div; break; - case ADIVU: p = prog_divu; break; - case AMOD: p = prog_mod; break; - case AMODU: p = prog_modu; break; - } - if(p != UP && thumb != p->from.sym->thumb) - p->from.sym->foreign = 1; -} - void nocache(Prog *p) { diff --git a/utils/tl/obj.c b/utils/tl/obj.c index 95b50f4f..6cc64dc0 100644 --- a/utils/tl/obj.c +++ b/utils/tl/obj.c @@ -242,15 +242,12 @@ main(int argc, char *argv[]) zerosig("edata"); zerosig("end"); if(dlm){ - initdiv(); import(); HEADTYPE = 2; INITTEXT = INITDAT = 0; INITRND = 8; INITENTRY = EXPTAB; } - else - divsig(); export(); } patch(); diff --git a/utils/tl/pass.c b/utils/tl/pass.c index e4322df5..c3725e74 100644 --- a/utils/tl/pass.c +++ b/utils/tl/pass.c @@ -512,10 +512,6 @@ reachable() int i, todo; char *a; - Reachable("_div"); - Reachable("_divu"); - Reachable("_mod"); - Reachable("_modu"); a = INITENTRY; if(*a >= '0' && *a <= '9') return; diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 69e0c5dd..f91b9d64 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -356,8 +356,9 @@ Optab thumboptab[] = { AMOVW, C_SCON, C_NONE, C_REG, 5, 2, 0 }, { AMOVW, C_BCON, C_NONE, C_REG, 47, 4, 0 }, { AMOVW, C_LCON, C_NONE, C_REG, 38, 2, 0, LFROM }, -// { AMVN, C_LCON, C_NONE, C_REG, 61, 4, 0 }, -// { AMVN, C_LCON, C_REG, C_REG, 61, 4, 0 }, + { AMVN, C_LCON, C_NONE, C_REG, 61, 4, 0 }, + { AMVN, C_LCON, C_REG, C_REG, 61, 4, 0 }, + { ARSB, C_LCON, C_REG, C_REG, 61, 4, 0 }, // { AADD, C_LCON, C_PC, C_REG, 6, 2, 0, LFROM }, // { AADD, C_LCON, C_SP, C_REG, 6, 2, 0, LFROM }, { AADD, C_SCON, C_NONE, C_SP, 7, 2, 0 }, @@ -524,10 +525,15 @@ Optab thumboptab[] = { AMOVW, C_REG, C_NONE, C_FCR, 59, 4, 0 }, { AMOVW, C_FCR, C_NONE, C_REG, 60, 4, 0 }, + { ADIV, C_REG, C_NONE, C_REG, 62, 4, 0 }, + { ADIVU, C_REG, C_NONE, C_REG, 62, 4, 0 }, + { AMOD, C_REG, C_NONE, C_REG, 63, 10, 0 }, + { AMODU, C_REG, C_NONE, C_REG, 64, 10, 0 }, + { AXXX, C_NONE, C_NONE, C_NONE, 0, 2, 0 }, }; -#define OPCNTSZ 62 +#define OPCNTSZ 65 int opcount[OPCNTSZ]; // is this too pessimistic ? @@ -1384,19 +1390,109 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); else r = p->reg; + thumbaclass(&p->from, p); + switch (p->as) { case AAND: - o1 = 0x0000f000 | r | (rt<<24) | ((instoffset & 0xff)<<16) | - ((instoffset & 0x700) << 20) | - ((instoffset & 0x800) >> 1); + o1 = 0x0000f000; + break; + case AORR: + o1 = 0x0000f040; + break; + case ARSB: + o1 = 0x0000f1c0; break; default: print("%A %d %d %d\n", p->as, instoffset, p->reg, p->to.reg); diag("not implemented: %A", p->as); break; } + o1 |= r | (rt<<24) | ((instoffset & 0xff)<<16) | + ((instoffset & 0x700) << 20) | + ((instoffset & 0x800) >> 1); + SPLIT_INS(o1, o2); + break; + + case 62: /* div(u) */ + rf = p->from.reg; + rt = p->to.reg; + if (p->reg == NREG) + r = rt; + else + r = p->reg; + + switch (p->as) { + case ADIV: + /* SDIV (4.6.126, ARM Architecture Reference Manual Thumb-2 Supplement) */ + o1 = 0xf0f0fb90; + break; + case ADIVU: + /* UDIV (4.6.198, ARM Architecture Reference Manual Thumb-2 Supplement) */ + o1 = 0xf0f0fbb0; + break; + default: + print("%A %d %d %d\n", p->as, rf, r, rt); + diag("not implemented: %A", p->as); + break; + } + + o1 |= r | (rf<<16) | (rt<<24); SPLIT_INS(o1, o2); break; + + case 63: /* mod */ + rf = p->from.reg; + rt = p->to.reg; + lowreg(p, rf); + lowreg(p, rt); + if (p->reg == NREG) + r = rt; + else + r = p->reg; + + /* rf is Rm in the manual, which is the second operand */ + + /* From ARM Architecture Reference Manual Thumb-2 Supplement, A-16: + x MOD y = x - y * (x DIV y) */ + /* TMP = N SDIV D or TMP = r / rf */ + o1 = 0xf0f0fb90 | (REGTMPT<<24) | r | (rf<<16); + /* MUL (4.6.84, ARM Architecture Reference Manual Thumb-2 Supplement) */ + /* TMP = D * (N DIV D) or TMP = TMP * rf */ + o3 = 0xf000fb00 | (REGTMPT<<24) | (rf<<16) | REGTMPT; + /* SUB (4.6.177, ARM Architecture Reference Manual Thumb-2 Supplement) */ + /* Q = N - D * (N DIV D) */ + o5 = 0x1a00 | (REGTMPT<<6) | (r<<3) | rt; + + SPLIT_INS(o1, o2); + SPLIT_INS(o3, o4); + break; + + case 64: /* modu */ + rf = p->from.reg; + rt = p->to.reg; + lowreg(p, rf); + lowreg(p, rt); + if (p->reg == NREG) + r = rt; + else + r = p->reg; + + /* rf is Rm in the manual, which is the second operand */ + + /* From ARM Architecture Reference Manual Thumb-2 Supplement, A-16: + x MOD y = x - y * (x DIV y) */ + /* TMP = N UDIV D or TMP = r / rf */ + o1 = 0xf0f0fbb0 | (REGTMPT<<24) | r | (rf<<16); + /* MUL (4.6.84, ARM Architecture Reference Manual Thumb-2 Supplement) */ + /* TMP = D * (N DIV D) or TMP = TMP * rf */ + o3 = 0xf000fb00 | (REGTMPT<<24) | (rf<<16) | REGTMPT; + /* SUB (4.6.177, ARM Architecture Reference Manual Thumb-2 Supplement) */ + /* Q = N - D * (N DIV D) */ + o5 = 0x1a00 | (REGTMPT<<6) | (r<<3) | rt; + + SPLIT_INS(o1, o2); + SPLIT_INS(o3, o4); + break; } v = p->pc; |
