summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/tl/l.h7
-rw-r--r--utils/tl/noop.c227
-rw-r--r--utils/tl/obj.c3
-rw-r--r--utils/tl/pass.c4
-rw-r--r--utils/tl/thumb.c108
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;