From 0070c024f32f589b2a1c18d04be34da3dd4a0305 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 30 Sep 2021 17:43:24 +0200 Subject: Update outlstring function in tc to match others --- utils/tc/swt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/tc/swt.c b/utils/tc/swt.c index b69a48b6..85a87d9b 100644 --- a/utils/tc/swt.c +++ b/utils/tc/swt.c @@ -196,7 +196,7 @@ outstring(char *s, long n) } long -outlstring(ushort *s, long n) +outlstring(TRune *s, long n) { char buf[2]; int c; -- cgit v1.2.3 From 14cbcf30bfdb1f32846bac56c20bcd7cf567239f Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 15 Jan 2022 16:42:30 +0100 Subject: Fixed typo. --- utils/tl/thumb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index f16175ea..736ce788 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -221,7 +221,7 @@ thumbaclass(Adr *a, Prog *p) } return C_GOK; case D_FCONST: - diag("D_FCONST in thumaclass"); + diag("D_FCONST in thumbaclass"); return C_FCON; case D_CONST: switch(a->name) { -- cgit v1.2.3 From 22efd8e5bdb47178266599cf3f3c72435ec45bcc Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 15 Jan 2022 16:51:18 +0100 Subject: Added FP instructions from the optab.c file. --- utils/tl/thumb.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 736ce788..f7a48a9c 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -450,6 +450,38 @@ Optab thumboptab[] = { AMOVHU, C_REG, C_NONE, C_LEXT, 31, 4, 0, LTO }, { AMOVBU, C_REG, C_NONE, C_LEXT, 31, 4, 0, LTO }, + { AMOVF, C_FREG, C_NONE, C_FEXT, 50, 4, REGSB }, + { AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP }, + { AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0 }, + + { AMOVF, C_FEXT, C_NONE, C_FREG, 51, 4, REGSB }, + { AMOVF, C_FAUTO,C_NONE, C_FREG, 51, 4, REGSP }, + { AMOVF, C_FOREG,C_NONE, C_FREG, 51, 4, 0 }, + + { AMOVF, C_FREG, C_NONE, C_LEXT, 52, 12, REGSB, LTO }, + { AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO }, + { AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO }, + + { AMOVF, C_LEXT, C_NONE, C_FREG, 53, 12, REGSB, LFROM }, + { AMOVF, C_LAUTO,C_NONE, C_FREG, 53, 12, REGSP, LFROM }, + { AMOVF, C_LOREG,C_NONE, C_FREG, 53, 12, 0, LFROM }, + + { AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO }, + { AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM }, + + { AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0 }, + { AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0 }, + { AADDF, C_FCON, C_NONE, C_FREG, 54, 4, 0 }, + { AADDF, C_FCON, C_REG, C_FREG, 54, 4, 0 }, + { AMOVF, C_FCON, C_NONE, C_FREG, 54, 4, 0 }, + { AMOVF, C_FREG, C_NONE, C_FREG, 54, 4, 0 }, + + { ACMPF, C_FREG, C_REG, C_NONE, 54, 4, 0 }, + { ACMPF, C_FCON, C_REG, C_NONE, 54, 4, 0 }, + + { AMOVFW, C_FREG, C_NONE, C_REG, 55, 4, 0 }, + { AMOVFW, C_REG, C_NONE, C_FREG, 55, 4, 0 }, + { AXXX, C_NONE, C_NONE, C_NONE, 0, 2, 0 }, }; -- cgit v1.2.3 From 283687da8fdd39209a0390f424ccbed3acc2680c Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 15 Jan 2022 16:52:11 +0100 Subject: Prevented change to regular ARM mode. --- utils/tl/obj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/tl/obj.c b/utils/tl/obj.c index 35c5f558..95b50f4f 100644 --- a/utils/tl/obj.c +++ b/utils/tl/obj.c @@ -1485,6 +1485,7 @@ static void puntfp(Prog *p) { USED(p); + return; /* floating point - punt for now */ curtext->reg = NREG; /* ARM */ curtext->from.sym->thumb = 0; -- cgit v1.2.3 From 6cb8866cc5d948f1b305fa0c50246ae291ba7867 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 15 Jan 2022 21:44:59 +0100 Subject: Renumbered FP opcodes and imported cases from the arm.c assembler. Added a layer of indirection to float constants to encode them correctly in Thumb instructions. --- utils/tl/thumb.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 182 insertions(+), 25 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index f7a48a9c..6cb3f86b 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -2,6 +2,7 @@ static long thumboprr(int); static long thumboprrr(int, int); +static long thumbopfp(int, int); static long thumbopirr(int , int); static long thumbopri(int); static long thumbophh(int); @@ -153,7 +154,6 @@ thumbaclass(Adr *a, Prog *p) diag("D_SHIFT in thumbaclass"); return C_SHIFT; case D_FREG: - diag("D_FREG in thumbaclass"); return C_FREG; case D_FPCR: diag("D_FPCR in thumbaclass"); @@ -221,7 +221,6 @@ thumbaclass(Adr *a, Prog *p) } return C_GOK; case D_FCONST: - diag("D_FCONST in thumbaclass"); return C_FCON; case D_CONST: switch(a->name) { @@ -450,42 +449,45 @@ Optab thumboptab[] = { AMOVHU, C_REG, C_NONE, C_LEXT, 31, 4, 0, LTO }, { AMOVBU, C_REG, C_NONE, C_LEXT, 31, 4, 0, LTO }, - { AMOVF, C_FREG, C_NONE, C_FEXT, 50, 4, REGSB }, - { AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP }, - { AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0 }, + { AMOVF, C_FREG, C_NONE, C_FEXT, 52, 4, REGSB }, + { AMOVF, C_FREG, C_NONE, C_FAUTO, 52, 4, REGSP }, + { AMOVF, C_FREG, C_NONE, C_FOREG, 52, 4, 0 }, - { AMOVF, C_FEXT, C_NONE, C_FREG, 51, 4, REGSB }, - { AMOVF, C_FAUTO,C_NONE, C_FREG, 51, 4, REGSP }, - { AMOVF, C_FOREG,C_NONE, C_FREG, 51, 4, 0 }, + { AMOVF, C_FEXT, C_NONE, C_FREG, 53, 4, REGSB }, + { AMOVF, C_FAUTO,C_NONE, C_FREG, 53, 4, REGSP }, + { AMOVF, C_FOREG,C_NONE, C_FREG, 53, 4, 0 }, - { AMOVF, C_FREG, C_NONE, C_LEXT, 52, 12, REGSB, LTO }, - { AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO }, - { AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO }, + { AMOVF, C_FREG, C_NONE, C_LEXT, 54, 12, REGSB, LTO }, + { AMOVF, C_FREG, C_NONE, C_LAUTO, 54, 12, REGSP, LTO }, + { AMOVF, C_FREG, C_NONE, C_LOREG, 54, 12, 0, LTO }, - { AMOVF, C_LEXT, C_NONE, C_FREG, 53, 12, REGSB, LFROM }, - { AMOVF, C_LAUTO,C_NONE, C_FREG, 53, 12, REGSP, LFROM }, - { AMOVF, C_LOREG,C_NONE, C_FREG, 53, 12, 0, LFROM }, + { AMOVF, C_LEXT, C_NONE, C_FREG, 55, 12, REGSB, LFROM }, + { AMOVF, C_LAUTO,C_NONE, C_FREG, 55, 12, REGSP, LFROM }, + { AMOVF, C_LOREG,C_NONE, C_FREG, 55, 12, 0, LFROM }, { AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO }, { AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM }, - { AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0 }, - { AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0 }, - { AADDF, C_FCON, C_NONE, C_FREG, 54, 4, 0 }, - { AADDF, C_FCON, C_REG, C_FREG, 54, 4, 0 }, - { AMOVF, C_FCON, C_NONE, C_FREG, 54, 4, 0 }, - { AMOVF, C_FREG, C_NONE, C_FREG, 54, 4, 0 }, + { AADDF, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { AADDF, C_FREG, C_REG, C_FREG, 56, 4, 0 }, + { AADDF, C_FCON, C_NONE, C_FREG, 56, 4, 0 }, + { AADDF, C_FCON, C_REG, C_FREG, 56, 4, 0 }, + { AMOVF, C_FCON, C_NONE, C_FREG, 56, 4, 0 }, + { AMOVF, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, - { ACMPF, C_FREG, C_REG, C_NONE, 54, 4, 0 }, - { ACMPF, C_FCON, C_REG, C_NONE, 54, 4, 0 }, + { ACMPF, C_FREG, C_REG, C_NONE, 56, 4, 0 }, + { ACMPF, C_FCON, C_REG, C_NONE, 56, 4, 0 }, - { AMOVFW, C_FREG, C_NONE, C_REG, 55, 4, 0 }, - { AMOVFW, C_REG, C_NONE, C_FREG, 55, 4, 0 }, + { AMOVFW, C_FREG, C_NONE, C_REG, 57, 4, 0 }, + { AMOVFW, C_REG, C_NONE, C_FREG, 57, 4, 0 }, + + { AMOVW, C_REG, C_NONE, C_FCR, 58, 4, 0 }, + { AMOVW, C_FCR, C_NONE, C_REG, 59, 4, 0 }, { AXXX, C_NONE, C_NONE, C_NONE, 0, 2, 0 }, }; -#define OPCNTSZ 52 +#define OPCNTSZ 60 int opcount[OPCNTSZ]; // is this too pessimistic ? @@ -674,6 +676,18 @@ thumbbuildop() } } +/* Map chipfloat indices to high and low immediate constant values for VMOV */ +static int thumbfloatmap[] = { + 0x7fffffff, /* Placeholder for zero */ + 0x00000007, /* 1 = 2**0 * 1 */ + 0x00000000, /* 2 = 2**1 * 1 */ + 0x00080000, /* 3 = 2**1 * 1.5 */ + 0x00000001, /* 4 = 2**2 * 1 */ + 0x00040001, /* 5 = 2**2 * 1.25 */ + 0x00000006, /* 0.5 = 2**-1 * 1 */ + 0x00040002, /* 10 = 2**3 * 1.25 */ +}; + void thumbasmout(Prog *p, Optab *o) { @@ -1157,6 +1171,117 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); o1 = mvlh(REGPC, REGLINK); // mov pc, lr o2 = mvlh(rt, REGPC); // mov r, pc break; + + case 52: /* floating point store */ + v = regoff(&p->to); + r = p->to.reg; + if(r == NREG) + r = o->param; + o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p); + break; + + case 53: /* floating point load */ + v = regoff(&p->from); + r = p->from.reg; + if(r == NREG) + r = o->param; + o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20); + break; + + case 54: /* floating point store, long offset UGLY */ + o1 = omvl(p, &p->to, REGTMP); + if(!o1) + break; + r = p->to.reg; + if(r == NREG) + r = o->param; + o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; + o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); + break; + + case 55: /* floating point load, long offset UGLY */ + o1 = omvl(p, &p->from, REGTMP); + if(!o1) + break; + r = p->from.reg; + if(r == NREG) + r = o->param; + o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; + o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); + break; + + case 56: /* floating point arith */ + o1 = thumbopfp(p->as, p->scond); + if(p->from.type == D_FCONST) { + rf = chipfloat(p->from.ieee); + if(rf < 0){ + diag("invalid floating-point immediate\n%P", p); + rf = 0; + } + } else + rf = p->from.reg; + + rt = p->to.reg; + r = p->reg; + if(p->to.type == D_NONE) + rt = 0; /* CMP[FD] */ + else if(r == NREG) + r = rt; + + switch (p->as) { + case AADDF: + /* VADD (ARMv7-M ARM, A7.7.222) */ + o1 |= (rf >> 1) | ((rf & 1) << 23) | /* Vn */ + ((r & 0x1e)<<15) | ((r & 1)<<21) | /* Vm */ + ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + break; + case AMOVF: + if(p->from.type == D_FCONST) { + if (rf == 0) { + /* Float constant was zero */ + /* VSUB rt, rt, rt (ARMv7-M ARM, A7.7.257) */ + o1 ^= 1 << 7; + o1 |= (rt >> 1) | ((rt & 1) << 23); /* Vn */ + o1 |= ((rt & 0x1e)<<15) | ((rt & 1)<<21); /* Vm */ + } else { + /* VMOV immediate (ARMv7-M ARM, A7.7.236) */ + o1 ^= 1 << 22; + o1 |= thumbfloatmap[rf]; + } + } else { + /* VMOV register (ARMv7-M ARM, A7.7.237) */ + o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21); /* Vm */ + } + o1 |= ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + } + /* Encode the 32-bit instruction as two 16-bit ones */ + o2 = o1 >> 16; + o1 = o1 & 0xffff; + break; + + case 57: /* floating point fix and float */ + o1 = oprrr(p->as, p->scond); + rf = p->from.reg; + rt = p->to.reg; + if(p->to.type == D_NONE){ + rt = 0; + diag("to.type==D_NONE (asm/fp)"); + } + if(p->from.type == D_REG) + o1 |= (rf<<12) | (rt<<16); + else + o1 |= rf | (rt<<12); + break; + + case 58: /* move to FP[CS]R */ + o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); + o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12); + break; + + case 59: /* move from FP[CS]R */ + o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); + o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); + break; } v = p->pc; @@ -1309,6 +1434,38 @@ thumboprrr(int a, int ld) return 0; } +long +thumbopfp(int a, int sc) +{ + long o = 0; + + switch(a) { + case AADDD: return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7); + case AADDF: return o | (0x0a<<24) | (0x0<<16) | (0xee<<8) | 0x30; + case AMULD: return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7); + case AMULF: return o | (0xe<<24) | (0x1<<20) | (1<<8); + case ASUBD: return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7); + case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8); + case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7); + case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8); + case ACMPD: + case ACMPF: return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4); /* arguably, ACMPF should expand to RNDF, CMPD */ + + case AMOVF: + case AMOVDF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb0; + case AMOVD: + case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); + + case AMOVWF: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4); + case AMOVWD: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7); + case AMOVFW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4); + case AMOVDW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7); + } + diag("bad fp %d", a); + prasm(curp); + return 0; +} + static long thumbopri(int a) { -- cgit v1.2.3 From 8d9c92cd784755be1717d0cedc699e133196d09c Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 15 Jan 2022 22:40:33 +0100 Subject: Removed unused array entry. --- utils/tl/thumb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 6cb3f86b..acc4f325 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -678,7 +678,6 @@ thumbbuildop() /* Map chipfloat indices to high and low immediate constant values for VMOV */ static int thumbfloatmap[] = { - 0x7fffffff, /* Placeholder for zero */ 0x00000007, /* 1 = 2**0 * 1 */ 0x00000000, /* 2 = 2**1 * 1 */ 0x00080000, /* 3 = 2**1 * 1.5 */ @@ -1246,7 +1245,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); } else { /* VMOV immediate (ARMv7-M ARM, A7.7.236) */ o1 ^= 1 << 22; - o1 |= thumbfloatmap[rf]; + o1 |= thumbfloatmap[rf - 1]; } } else { /* VMOV register (ARMv7-M ARM, A7.7.237) */ -- cgit v1.2.3 From bfe30ae5f499e80e6dfbffc1328e315be6be6f0b Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 17 Jan 2022 23:30:40 +0100 Subject: Worked on converting ARM instructions to Thumb instructions for floating point handling. --- utils/tl/thumb.c | 107 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 18 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index acc4f325..4c10ff1a 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -3,6 +3,8 @@ static long thumboprr(int); static long thumboprrr(int, int); static long thumbopfp(int, int); +static long thumbomvl(Prog *p, Adr *a, int dr); +static long thumbofsr(int a, int r, long v, int b, Prog *p); static long thumbopirr(int , int); static long thumbopri(int); static long thumbophh(int); @@ -14,6 +16,11 @@ static void numr(Prog *, int, int, int); static void regis(Prog *, int, int, int); static void dis(int, int); +/* Encode the 32-bit instructions as two 16-bit ones */ +#define SPLIT_INS(filled, empty) \ + empty = filled >> 16; \ + filled = filled & 0xffff; + // build a constant using neg, add and shift - only worth it if < 6 bytes */ static int immbuildcon(int c, Prog *p) @@ -49,7 +56,7 @@ immoreg(int off, Prog *p) if(off < 0) return C_GOREG; - if(as == AMOVW) + if(as == AMOVW || as == AMOVF) v = 4; else if(as == AMOVH || as == AMOVHU) v = 2; @@ -81,8 +88,8 @@ immacon(int off, Prog *p, int t1, int t2) static int immauto(int off, Prog *p) { - if(p->as != AMOVW) - diag("bad op in immauto"); + if(p->as != AMOVW && p->as != AMOVF) + diag("bad op %d in immauto", p->as); mult(p, off, 4); if(off >= 0 && off <= 1020) return C_SAUTO; @@ -457,13 +464,13 @@ Optab thumboptab[] = { AMOVF, C_FAUTO,C_NONE, C_FREG, 53, 4, REGSP }, { AMOVF, C_FOREG,C_NONE, C_FREG, 53, 4, 0 }, - { AMOVF, C_FREG, C_NONE, C_LEXT, 54, 12, REGSB, LTO }, - { AMOVF, C_FREG, C_NONE, C_LAUTO, 54, 12, REGSP, LTO }, - { AMOVF, C_FREG, C_NONE, C_LOREG, 54, 12, 0, LTO }, + { AMOVF, C_FREG, C_NONE, C_LEXT, 54, 8, REGSB, LTO }, + { AMOVF, C_FREG, C_NONE, C_LAUTO, 54, 8, REGSP, LTO }, + { AMOVF, C_FREG, C_NONE, C_LOREG, 54, 8, 0, LTO }, - { AMOVF, C_LEXT, C_NONE, C_FREG, 55, 12, REGSB, LFROM }, - { AMOVF, C_LAUTO,C_NONE, C_FREG, 55, 12, REGSP, LFROM }, - { AMOVF, C_LOREG,C_NONE, C_FREG, 55, 12, 0, LFROM }, + { AMOVF, C_LEXT, C_NONE, C_FREG, 55, 8, REGSB, LFROM }, + { AMOVF, C_LAUTO,C_NONE, C_FREG, 55, 8, REGSP, LFROM }, + { AMOVF, C_LOREG,C_NONE, C_FREG, 55, 8, 0, LFROM }, { AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO }, { AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM }, @@ -1176,7 +1183,10 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); r = p->to.reg; if(r == NREG) r = o->param; - o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p); + o1 = thumbofsr(p->as, p->from.reg, v, r, p); + /* Encode the 32-bit instruction as two 16-bit ones */ +/* o2 = o1 >> 16; + o1 = o1 & 0xffff;*/ break; case 53: /* floating point load */ @@ -1184,29 +1194,33 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); r = p->from.reg; if(r == NREG) r = o->param; - o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20); + o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<4); break; case 54: /* floating point store, long offset UGLY */ - o1 = omvl(p, &p->to, REGTMP); + o1 = thumbomvl(p, &p->to, REGTMPT); if(!o1) break; r = p->to.reg; if(r == NREG) r = o->param; - o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; - o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); + /* ADD (ARM ARM Thumb-2 Supplement, 4.6.4), T2 */ + o2 = 0x4400 | ((REGTMPT & 0x8) << 4) | (r << 3) | (REGTMPT & 0x7); + o3 = thumbofsr(p->as, p->from.reg, 0, REGTMPT, p); + SPLIT_INS(o3, o4) break; case 55: /* floating point load, long offset UGLY */ - o1 = omvl(p, &p->from, REGTMP); + o1 = thumbomvl(p, &p->from, REGTMPT); if(!o1) break; r = p->from.reg; if(r == NREG) r = o->param; - o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; - o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); + /* ADD (ARM ARM Thumb-2 Supplement, 4.6.4), T2 */ + o2 = 0x4400 | ((REGTMPT & 0x8) << 4) | (r << 3) | (REGTMPT & 0x7); + o3 = thumbofsr(p->as, p->to.reg, 0, REGTMPT, p) | (1<<4); + SPLIT_INS(o3, o4) break; case 56: /* floating point arith */ @@ -1259,7 +1273,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 57: /* floating point fix and float */ - o1 = oprrr(p->as, p->scond); + o1 = thumbopfp(p->as, p->scond); rf = p->from.reg; rt = p->to.reg; if(p->to.type == D_NONE){ @@ -1465,6 +1479,39 @@ thumbopfp(int a, int sc) return 0; } +static long +thumbofsr(int a, int r, long v, int b, Prog *p) +{ + long o; + + /* VSTR (ARMv7-M ARM, A7.7.256), encoding T2 */ + o = 0x0a00ed00 | (1 << 7); /* Set U (add offset) by default */ + if(v < 0) { + v = -v; + o ^= 1 << 7; /* clear U if offset is negative */ + } + if(v & 3) + diag("odd offset for floating point op: %d\n%P", v, p); + else if(v >= (1<<10)) + diag("literal span too large: %d\n%P", v, p); + o |= ((v>>2) & 0xFF) << 16; /* offset */ + o |= b; /* Rn */ + o |= ((r & 0x1e) << 27) | ((r & 1) << 6); /* Vd */ + + switch(a) { + default: + diag("bad fst %A", a); + case AMOVD: + diag("bad fst %A", a); + case AMOVF: + break; + } + + /* The caller will OR the result with 1 << 4 to create a load, if required */ + /* VLDR (ARMv7-M ARM, A7.7.233), encoding T2 */ + return o; +} + static long thumbopri(int a) { @@ -1536,6 +1583,30 @@ thumbopmv(int a, int ld) return 0; } +static long +thumbomvl(Prog *p, Adr *a, int dr) +{ + long v, o1; + if(!p->cond) { + thumbaclass(a, p); + v = immrot(~instoffset); + if(v == 0) { + diag("missing literal"); + prasm(p); + return 0; + } + print("omvl: %d\n", dr); + o1 = thumboprrr(AMVN, dr); + o1 |= v; + } else { + v = p->cond->pc - p->pc - 4; + /* A PC-relative load into dr */ + //o1 = 0x4800 | (dr << 8) | (v >> 1); + o1 = mv(p, dr, v); + } + return o1; +} + static void lowreg(Prog *p, int r) { -- cgit v1.2.3 From 01ae1f3b4a7aa5bf32e3ad3c2911e6f6ba723e71 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 18 Jan 2022 22:05:00 +0100 Subject: Speculatively enable more FP instructions. --- utils/tl/thumb.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 4c10ff1a..ab878836 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -541,9 +541,11 @@ brextra(Prog *p) static long mv(Prog *p, int r, int off) { +// print("mv %d %x\n", r, off); int v, o; if(p != nil && p->cond != nil){ // in literal pool v = p->cond->pc - p->pc - 4; + print("%x %x\n", p->cond->pc, p->pc); if(p->cond->pc & 3) diag("mv: bad literal pool alignment"); if(v & 3) @@ -557,6 +559,7 @@ mv(Prog *p, int r, int off) numr(p, off, 0, 255); o = 0x4<<11; } +// print("MV %d %.8lux\n", off, o); o |= (r<<8) | off; return o; } @@ -1179,22 +1182,23 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 52: /* floating point store */ + diag("52", p); v = regoff(&p->to); r = p->to.reg; if(r == NREG) r = o->param; o1 = thumbofsr(p->as, p->from.reg, v, r, p); - /* Encode the 32-bit instruction as two 16-bit ones */ -/* o2 = o1 >> 16; - o1 = o1 & 0xffff;*/ + SPLIT_INS(o1, o2); break; case 53: /* floating point load */ + diag("53", p); v = regoff(&p->from); r = p->from.reg; if(r == NREG) r = o->param; - o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<4); + o1 = thumbofsr(p->as, p->to.reg, v, r, p) | (1<<4); + SPLIT_INS(o1, o2); break; case 54: /* floating point store, long offset UGLY */ @@ -1267,9 +1271,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); } o1 |= ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ } - /* Encode the 32-bit instruction as two 16-bit ones */ - o2 = o1 >> 16; - o1 = o1 & 0xffff; + SPLIT_INS(o1, o2); break; case 57: /* floating point fix and float */ @@ -1281,17 +1283,20 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); diag("to.type==D_NONE (asm/fp)"); } if(p->from.type == D_REG) - o1 |= (rf<<12) | (rt<<16); + o1 |= (rf<<28) | ((rt & 1)<<23) | ((rt & 0x1e)>>1); else - o1 |= rf | (rt<<12); + o1 |= (rt<<28) | ((rf & 1)<<23) | ((rf & 0x1e)>>1); + SPLIT_INS(o1, o2); break; case 58: /* move to FP[CS]R */ + diag("58", p); o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12); break; case 59: /* move from FP[CS]R */ + diag("59", p); o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); break; @@ -1469,10 +1474,10 @@ thumbopfp(int a, int sc) case AMOVD: case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); - case AMOVWF: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4); - case AMOVWD: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7); - case AMOVFW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4); - case AMOVDW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7); + case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (0<<4); + case AMOVWD: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (0<<4); + case AMOVFW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<4); + case AMOVDW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (1<<4); } diag("bad fp %d", a); prasm(curp); -- cgit v1.2.3 From db3257ec1eca2eb282aa53e1822fd5fd92768b1a Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 18 Jan 2022 23:17:22 +0100 Subject: Handled loads and stores using different base registers with slightly different instructions. --- utils/tl/thumb.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index ab878836..c150c808 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -464,11 +464,11 @@ Optab thumboptab[] = { AMOVF, C_FAUTO,C_NONE, C_FREG, 53, 4, REGSP }, { AMOVF, C_FOREG,C_NONE, C_FREG, 53, 4, 0 }, - { AMOVF, C_FREG, C_NONE, C_LEXT, 54, 8, REGSB, LTO }, + { AMOVF, C_FREG, C_NONE, C_LEXT, 54, 6, REGSB, LTO }, { AMOVF, C_FREG, C_NONE, C_LAUTO, 54, 8, REGSP, LTO }, { AMOVF, C_FREG, C_NONE, C_LOREG, 54, 8, 0, LTO }, - { AMOVF, C_LEXT, C_NONE, C_FREG, 55, 8, REGSB, LFROM }, + { AMOVF, C_LEXT, C_NONE, C_FREG, 55, 6, REGSB, LFROM }, { AMOVF, C_LAUTO,C_NONE, C_FREG, 55, 8, REGSP, LFROM }, { AMOVF, C_LOREG,C_NONE, C_FREG, 55, 8, 0, LFROM }, @@ -1202,29 +1202,47 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 54: /* floating point store, long offset UGLY */ + /* Load an address or offset from a PC-relative address */ o1 = thumbomvl(p, &p->to, REGTMPT); if(!o1) break; r = p->to.reg; if(r == NREG) r = o->param; - /* ADD (ARM ARM Thumb-2 Supplement, 4.6.4), T2 */ - o2 = 0x4400 | ((REGTMPT & 0x8) << 4) | (r << 3) | (REGTMPT & 0x7); - o3 = thumbofsr(p->as, p->from.reg, 0, REGTMPT, p); - SPLIT_INS(o3, o4) + if (o->param == REGSB) { + /* Store directly to the address */ + o2 = thumbofsr(p->as, p->from.reg, 0, REGTMPT, p); + SPLIT_INS(o2, o3) + } else { + /* Add the offset to the stack pointer */ + /* ADD (ARM ARM Thumb-2 Supplement, 4.6.4), T2 */ + o2 = 0x4400 | ((REGTMPT & 0x8) << 4) | (r << 3) | (REGTMPT & 0x7); + /* Store to the calculated address */ + o3 = thumbofsr(p->as, p->from.reg, 0, REGTMPT, p); + SPLIT_INS(o3, o4) + } break; case 55: /* floating point load, long offset UGLY */ + /* Load an address or offset from a PC-relative address */ o1 = thumbomvl(p, &p->from, REGTMPT); if(!o1) break; r = p->from.reg; if(r == NREG) r = o->param; - /* ADD (ARM ARM Thumb-2 Supplement, 4.6.4), T2 */ - o2 = 0x4400 | ((REGTMPT & 0x8) << 4) | (r << 3) | (REGTMPT & 0x7); - o3 = thumbofsr(p->as, p->to.reg, 0, REGTMPT, p) | (1<<4); - SPLIT_INS(o3, o4) + if (o->param == REGSB) { + /* Load directly from the address */ + o2 = thumbofsr(p->as, p->to.reg, 0, REGTMPT, p) | (1<<4); + SPLIT_INS(o2, o3) + } else { + /* Add the offset to the stack pointer */ + /* ADD (ARM ARM Thumb-2 Supplement, 4.6.4), T2 */ + o2 = 0x4400 | ((REGTMPT & 0x8) << 4) | (r << 3) | (REGTMPT & 0x7); + /* Load from the calculated address */ + o3 = thumbofsr(p->as, p->to.reg, 0, REGTMPT, p) | (1<<4); + SPLIT_INS(o3, o4) + } break; case 56: /* floating point arith */ -- cgit v1.2.3 From 14ec6600b6d1c9a95fa80d2708a1e179c6d9b509 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 20 Jan 2022 01:26:54 +0100 Subject: Changed an entry in the opcode table to reflect the direction of conversion. Added references to instruction information. --- utils/tl/thumb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index c150c808..b5594b91 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -486,7 +486,7 @@ Optab thumboptab[] = { ACMPF, C_FCON, C_REG, C_NONE, 56, 4, 0 }, { AMOVFW, C_FREG, C_NONE, C_REG, 57, 4, 0 }, - { AMOVFW, C_REG, C_NONE, C_FREG, 57, 4, 0 }, + { AMOVWF, C_REG, C_NONE, C_FREG, 57, 4, 0 }, { AMOVW, C_REG, C_NONE, C_FCR, 58, 4, 0 }, { AMOVW, C_FCR, C_NONE, C_REG, 59, 4, 0 }, @@ -1492,8 +1492,10 @@ thumbopfp(int a, int sc) case AMOVD: case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); + /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=0 */ case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (0<<4); case AMOVWD: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (0<<4); + /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=1 */ case AMOVFW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<4); case AMOVDW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (1<<4); } -- cgit v1.2.3 From 02188d2a161248aa89ae9fddd347b61e56d00766 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 28 Jan 2022 01:47:05 +0100 Subject: Started trying to add missing instructions. --- utils/tl/span.c | 6 +++++- utils/tl/thumb.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/utils/tl/span.c b/utils/tl/span.c index 85f27621..8ceaf631 100644 --- a/utils/tl/span.c +++ b/utils/tl/span.c @@ -771,6 +771,7 @@ Optab* oplook(Prog *p) { int a1, a2, a3, r; + int oa1, oa2, oa3; char *c1, *c3; Optab *o, *e; Optab *otab; @@ -808,6 +809,9 @@ oplook(Prog *p) a2 = C_NONE; if(p->reg != NREG) a2 = C_REG; + + oa1 = a1; oa2 = a2; oa3 = a3; + r = p->as; o = orange[r].start; if(o == 0) { @@ -834,7 +838,7 @@ oplook(Prog *p) return o; } diag("illegal combination %A %d %d %d", - p->as, a1, a2, a3); + p->as, oa1, oa2, oa3); prasm(p); if(o == 0) o = otab; diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index b5594b91..a305b531 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -56,7 +56,7 @@ immoreg(int off, Prog *p) if(off < 0) return C_GOREG; - if(as == AMOVW || as == AMOVF) + if(as == AMOVW || as == AMOVF || as == AMOVD) v = 4; else if(as == AMOVH || as == AMOVHU) v = 2; @@ -88,11 +88,12 @@ immacon(int off, Prog *p, int t1, int t2) static int immauto(int off, Prog *p) { - if(p->as != AMOVW && p->as != AMOVF) + if(p->as != AMOVW && p->as != AMOVF && p->as != AMOVD) diag("bad op %d in immauto", p->as); mult(p, off, 4); if(off >= 0 && off <= 1020) return C_SAUTO; + return C_LAUTO; } @@ -460,18 +461,28 @@ Optab thumboptab[] = { AMOVF, C_FREG, C_NONE, C_FAUTO, 52, 4, REGSP }, { AMOVF, C_FREG, C_NONE, C_FOREG, 52, 4, 0 }, + { AMOVD, C_FREG, C_NONE, C_SAUTO, 52, 4, REGSP }, + { AMOVD, C_FREG, C_NONE, C_SOREG, 52, 4, 0 }, + { AMOVF, C_FEXT, C_NONE, C_FREG, 53, 4, REGSB }, { AMOVF, C_FAUTO,C_NONE, C_FREG, 53, 4, REGSP }, { AMOVF, C_FOREG,C_NONE, C_FREG, 53, 4, 0 }, + { AMOVD, C_SAUTO,C_NONE, C_FREG, 53, 4, REGSP }, + { AMOVD, C_SOREG,C_NONE, C_FREG, 53, 4, 0 }, + { AMOVF, C_FREG, C_NONE, C_LEXT, 54, 6, REGSB, LTO }, { AMOVF, C_FREG, C_NONE, C_LAUTO, 54, 8, REGSP, LTO }, { AMOVF, C_FREG, C_NONE, C_LOREG, 54, 8, 0, LTO }, + { AMOVD, C_FREG, C_NONE, C_LEXT, 54, 6, REGSB, LTO }, + { AMOVF, C_LEXT, C_NONE, C_FREG, 55, 6, REGSB, LFROM }, { AMOVF, C_LAUTO,C_NONE, C_FREG, 55, 8, REGSP, LFROM }, { AMOVF, C_LOREG,C_NONE, C_FREG, 55, 8, 0, LFROM }, + { AMOVD, C_LEXT, C_NONE, C_FREG, 55, 6, REGSB, LFROM }, + { AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO }, { AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM }, @@ -482,11 +493,28 @@ Optab thumboptab[] = { AMOVF, C_FCON, C_NONE, C_FREG, 56, 4, 0 }, { AMOVF, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { AADDD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { AADDD, C_FREG, C_REG, C_FREG, 56, 4, 0 }, + { ASUBD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { ASUBD, C_FREG, C_REG, C_FREG, 56, 4, 0 }, + { ADIVD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { AMULD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + + { AMOVD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { AMOVD, C_FCON, C_NONE, C_FREG, 56, 4, 0 }, + { ACMPF, C_FREG, C_REG, C_NONE, 56, 4, 0 }, { ACMPF, C_FCON, C_REG, C_NONE, 56, 4, 0 }, + { ACMPD, C_FREG, C_REG, C_NONE, 56, 4, 0 }, + { ACMPD, C_FCON, C_REG, C_NONE, 56, 4, 0 }, + { AMOVFW, C_FREG, C_NONE, C_REG, 57, 4, 0 }, { AMOVWF, C_REG, C_NONE, C_FREG, 57, 4, 0 }, + { AMOVWD, C_REG, C_NONE, C_FREG, 57, 4, 0 }, + { AMOVDW, C_FREG, C_NONE, C_REG, 57, 4, 0 }, + { AMOVFD, C_FREG, C_NONE, C_FREG, 57, 4, 0 }, + { AMOVDF, C_FREG, C_NONE, C_FREG, 57, 4, 0 }, { AMOVW, C_REG, C_NONE, C_FCR, 58, 4, 0 }, { AMOVW, C_FCR, C_NONE, C_REG, 59, 4, 0 }, @@ -541,11 +569,9 @@ brextra(Prog *p) static long mv(Prog *p, int r, int off) { -// print("mv %d %x\n", r, off); int v, o; if(p != nil && p->cond != nil){ // in literal pool v = p->cond->pc - p->pc - 4; - print("%x %x\n", p->cond->pc, p->pc); if(p->cond->pc & 3) diag("mv: bad literal pool alignment"); if(v & 3) @@ -559,7 +585,6 @@ mv(Prog *p, int r, int off) numr(p, off, 0, 255); o = 0x4<<11; } -// print("MV %d %.8lux\n", off, o); o |= (r<<8) | off; return o; } @@ -1182,7 +1207,6 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 52: /* floating point store */ - diag("52", p); v = regoff(&p->to); r = p->to.reg; if(r == NREG) @@ -1192,7 +1216,6 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 53: /* floating point load */ - diag("53", p); v = regoff(&p->from); r = p->from.reg; if(r == NREG) @@ -1271,6 +1294,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ break; case AMOVF: + case AMOVD: /* TODO: actually use double precision */ if(p->from.type == D_FCONST) { if (rf == 0) { /* Float constant was zero */ @@ -1288,6 +1312,9 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21); /* Vm */ } o1 |= ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + default: + diag("not implemented: %A", p->as); + break; } SPLIT_INS(o1, o2); break; @@ -1484,9 +1511,12 @@ thumbopfp(int a, int sc) case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8); case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7); case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8); + /* VCMP (ARMv7-M ARM, A7.7.223), encoding T1 */ case ACMPD: - case ACMPF: return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4); /* arguably, ACMPF should expand to RNDF, CMPD */ + case ACMPF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb4; + /* arguably, ACMPF should expand to RNDF, CMPD */ + /* VMOV (register) (ARMv7-M ARM, A7.7.237) */ case AMOVF: case AMOVDF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb0; case AMOVD: @@ -1527,7 +1557,9 @@ thumbofsr(int a, int r, long v, int b, Prog *p) default: diag("bad fst %A", a); case AMOVD: - diag("bad fst %A", a); + /* Make the encoding T1 instead of T2 for double precision */ + o &= ~(1 << 24); + break; case AMOVF: break; } -- cgit v1.2.3 From 5f71fa5e8be0cdcdaadcf3f2dc1494de4228ea48 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 28 Jan 2022 22:27:02 +0100 Subject: Added entries to the optab for combinations that occur when compiling bits of a kernel. Split ACMPF handling like the VFP support does in 5l. --- utils/tl/thumb.c | 58 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index a305b531..ff4b4a03 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -503,26 +503,26 @@ Optab thumboptab[] = { AMOVD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, { AMOVD, C_FCON, C_NONE, C_FREG, 56, 4, 0 }, - { ACMPF, C_FREG, C_REG, C_NONE, 56, 4, 0 }, - { ACMPF, C_FCON, C_REG, C_NONE, 56, 4, 0 }, + { ACMPF, C_FREG, C_REG, C_NONE, 57, 8, 0 }, + { ACMPF, C_FCON, C_REG, C_NONE, 57, 8, 0 }, - { ACMPD, C_FREG, C_REG, C_NONE, 56, 4, 0 }, - { ACMPD, C_FCON, C_REG, C_NONE, 56, 4, 0 }, + { ACMPD, C_FREG, C_REG, C_NONE, 57, 8, 0 }, + { ACMPD, C_FCON, C_REG, C_NONE, 57, 8, 0 }, - { AMOVFW, C_FREG, C_NONE, C_REG, 57, 4, 0 }, - { AMOVWF, C_REG, C_NONE, C_FREG, 57, 4, 0 }, - { AMOVWD, C_REG, C_NONE, C_FREG, 57, 4, 0 }, - { AMOVDW, C_FREG, C_NONE, C_REG, 57, 4, 0 }, - { AMOVFD, C_FREG, C_NONE, C_FREG, 57, 4, 0 }, - { AMOVDF, C_FREG, C_NONE, C_FREG, 57, 4, 0 }, + { AMOVFW, C_FREG, C_NONE, C_REG, 58, 4, 0 }, + { AMOVWF, C_REG, C_NONE, C_FREG, 58, 4, 0 }, + { AMOVWD, C_REG, C_NONE, C_FREG, 58, 4, 0 }, + { AMOVDW, C_FREG, C_NONE, C_REG, 58, 4, 0 }, + { AMOVFD, C_FREG, C_NONE, C_FREG, 58, 4, 0 }, + { AMOVDF, C_FREG, C_NONE, C_FREG, 58, 4, 0 }, - { AMOVW, C_REG, C_NONE, C_FCR, 58, 4, 0 }, - { AMOVW, C_FCR, C_NONE, C_REG, 59, 4, 0 }, + { AMOVW, C_REG, C_NONE, C_FCR, 59, 4, 0 }, + { AMOVW, C_FCR, C_NONE, C_REG, 60, 4, 0 }, { AXXX, C_NONE, C_NONE, C_NONE, 0, 2, 0 }, }; -#define OPCNTSZ 60 +#define OPCNTSZ 61 int opcount[OPCNTSZ]; // is this too pessimistic ? @@ -1281,9 +1281,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); rt = p->to.reg; r = p->reg; - if(p->to.type == D_NONE) - rt = 0; /* CMP[FD] */ - else if(r == NREG) + if(r == NREG) r = rt; switch (p->as) { @@ -1312,14 +1310,32 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21); /* Vm */ } o1 |= ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + break; default: + print("%A %d %d %d\n", p->as, rf, r, rt); diag("not implemented: %A", p->as); break; } SPLIT_INS(o1, o2); break; - case 57: /* floating point fix and float */ + case 57: /* floating point compare */ + o1 = thumbopfp(p->as, p->scond); + rf = p->from.reg; + rt = p->reg; + + /* VCMP (ARMv7-M ARM, A7.7.223) */ + o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21) | /* Vm */ + ((r & 0x1e)<<27) | ((r & 1)<<6); /* Vd */ + + /* VMRS (ARMv7-M ARM, A7.7.243) with Rt=15 (for flags) */ + o3 = 0x0a10eef1 | (15 << 28); + + SPLIT_INS(o1, o2); + SPLIT_INS(o3, o4); + break; + + case 58: /* floating point fix and float */ o1 = thumbopfp(p->as, p->scond); rf = p->from.reg; rt = p->to.reg; @@ -1334,14 +1350,14 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); SPLIT_INS(o1, o2); break; - case 58: /* move to FP[CS]R */ - diag("58", p); + case 59: /* move to FP[CS]R */ + diag("59", p); o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12); break; - case 59: /* move from FP[CS]R */ - diag("59", p); + case 60: /* move from FP[CS]R */ + diag("60", p); o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); break; -- cgit v1.2.3 From 6f8656685a07adf9aa36c24d912b4ce8f6099b46 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 31 Jan 2022 23:46:21 +0100 Subject: Added support for more floating point operations. Fixed bit flipping for a MOVD instruction. --- utils/tl/thumb.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index ff4b4a03..cb170c98 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -495,9 +495,13 @@ Optab thumboptab[] = { AADDD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, { AADDD, C_FREG, C_REG, C_FREG, 56, 4, 0 }, + { ASUBF, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { ASUBF, C_FREG, C_REG, C_FREG, 56, 4, 0 }, { ASUBD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, { ASUBD, C_FREG, C_REG, C_FREG, 56, 4, 0 }, { ADIVD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { ADIVF, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, + { AMULF, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, { AMULD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, { AMOVD, C_FREG, C_NONE, C_FREG, 56, 4, 0 }, @@ -1212,6 +1216,8 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); if(r == NREG) r = o->param; o1 = thumbofsr(p->as, p->from.reg, v, r, p); + if (p->as == AMOVD) + o1 |= 1 << 24; SPLIT_INS(o1, o2); break; @@ -1286,9 +1292,15 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); switch (p->as) { case AADDF: - /* VADD (ARMv7-M ARM, A7.7.222) */ - o1 |= (rf >> 1) | ((rf & 1) << 23) | /* Vn */ - ((r & 0x1e)<<15) | ((r & 1)<<21) | /* Vm */ + case AADDD: + case ADIVF: + case ADIVD: + case AMULF: + case AMULD: + case ASUBF: + case ASUBD: + o1 |= (r >> 1) | ((r & 1) << 23) | /* Vn */ + ((rf & 0x1e)<<15) | ((rf & 1)<<21) | /* Vm */ ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ break; case AMOVF: @@ -1310,6 +1322,8 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21); /* Vm */ } o1 |= ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + if (p->as == AMOVD) + o1 |= 1 << 24; break; default: print("%A %d %d %d\n", p->as, rf, r, rt); @@ -1519,14 +1533,18 @@ thumbopfp(int a, int sc) long o = 0; switch(a) { - case AADDD: return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7); - case AADDF: return o | (0x0a<<24) | (0x0<<16) | (0xee<<8) | 0x30; - case AMULD: return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7); - case AMULF: return o | (0xe<<24) | (0x1<<20) | (1<<8); - case ASUBD: return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7); - case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8); - case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7); - case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8); + /* VADD (ARMv7-M ARM, A7.7.222) */ + case AADDD: return o | (0x0b<<24) | (0xee<<8) | 0x30; + case AADDF: return o | (0x0a<<24) | (0xee<<8) | 0x30; + /* VMUL (ARMv7-M ARM, A7.7.245) */ + case AMULD: return o | (0x0b<<24) | (0xee<<8) | 0x20; + case AMULF: return o | (0x0a<<24) | (0xee<<8) | 0x20; + /* VSUB (ARMv7-M ARM, A7.7.257) */ + case ASUBD: return o | (0x0b<<24) | (0x4<<20) | (0xee<<8) | 0x30; + case ASUBF: return o | (0x0a<<24) | (0x4<<20) | (0xee<<8) | 0x30; + /* VDIV (ARMv7-M ARM, A7.7.229) */ + case ADIVD: return o | (0x0b<<24) | (0xee<<8) | 0x80; + case ADIVF: return o | (0x0a<<24) | (0xee<<8) | 0x80; /* VCMP (ARMv7-M ARM, A7.7.223), encoding T1 */ case ACMPD: case ACMPF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb4; @@ -1574,7 +1592,7 @@ thumbofsr(int a, int r, long v, int b, Prog *p) diag("bad fst %A", a); case AMOVD: /* Make the encoding T1 instead of T2 for double precision */ - o &= ~(1 << 24); + o |= 1 << 24; break; case AMOVF: break; @@ -1674,7 +1692,6 @@ thumbomvl(Prog *p, Adr *a, int dr) } else { v = p->cond->pc - p->pc - 4; /* A PC-relative load into dr */ - //o1 = 0x4800 | (dr << 8) | (v >> 1); o1 = mv(p, dr, v); } return o1; -- cgit v1.2.3 From a14823a44843753e10db14bb36eb1e80284f4074 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 2 Feb 2022 23:23:53 +0100 Subject: Brought the order of operations in line with the VFP instructions in 5l for easier comparison. Fixed encoding of MOVD and related operations so that their execution causes a trap to occur. --- utils/tl/thumb.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index cb170c98..ff7818f5 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1533,35 +1533,34 @@ thumbopfp(int a, int sc) long o = 0; switch(a) { + /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=0 */ + case AMOVWD: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (0<<4); + case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (0<<4); + /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=1 */ + case AMOVDW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (1<<4); + case AMOVFW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<4); + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1 */ + case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | (0xee<<8) | 0xb7; + case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | (0xee<<8) | 0xb7; + /* VMOV (register) (ARMv7-M ARM, A7.7.237) */ + case AMOVD: return o | (0x0b<<24) | (0x40<<16) | (0xee<<8) | 0xb0; + case AMOVF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb0; + /* VCMP (ARMv7-M ARM, A7.7.223), encoding T1 */ + case ACMPD: + case ACMPF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb4; + /* arguably, ACMPF should expand to RNDF, CMPD */ /* VADD (ARMv7-M ARM, A7.7.222) */ case AADDD: return o | (0x0b<<24) | (0xee<<8) | 0x30; case AADDF: return o | (0x0a<<24) | (0xee<<8) | 0x30; - /* VMUL (ARMv7-M ARM, A7.7.245) */ - case AMULD: return o | (0x0b<<24) | (0xee<<8) | 0x20; - case AMULF: return o | (0x0a<<24) | (0xee<<8) | 0x20; /* VSUB (ARMv7-M ARM, A7.7.257) */ case ASUBD: return o | (0x0b<<24) | (0x4<<20) | (0xee<<8) | 0x30; case ASUBF: return o | (0x0a<<24) | (0x4<<20) | (0xee<<8) | 0x30; + /* VMUL (ARMv7-M ARM, A7.7.245) */ + case AMULD: return o | (0x0b<<24) | (0xee<<8) | 0x20; + case AMULF: return o | (0x0a<<24) | (0xee<<8) | 0x20; /* VDIV (ARMv7-M ARM, A7.7.229) */ case ADIVD: return o | (0x0b<<24) | (0xee<<8) | 0x80; case ADIVF: return o | (0x0a<<24) | (0xee<<8) | 0x80; - /* VCMP (ARMv7-M ARM, A7.7.223), encoding T1 */ - case ACMPD: - case ACMPF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb4; - /* arguably, ACMPF should expand to RNDF, CMPD */ - - /* VMOV (register) (ARMv7-M ARM, A7.7.237) */ - case AMOVF: - case AMOVDF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb0; - case AMOVD: - case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); - - /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=0 */ - case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (0<<4); - case AMOVWD: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (0<<4); - /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=1 */ - case AMOVFW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<4); - case AMOVDW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (1<<4); } diag("bad fp %d", a); prasm(curp); -- cgit v1.2.3 From 6efe84435572f948d631c14b2cd4a40c6bd8e298 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 3 Feb 2022 02:28:35 +0100 Subject: Tidied up the thumbopfp function and added a case for ACMPD. --- utils/tl/thumb.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index ff7818f5..ed2943e0 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1532,35 +1532,37 @@ thumbopfp(int a, int sc) { long o = 0; + o |= 0xee << 8; + switch(a) { /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=0 */ - case AMOVWD: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (0<<4); - case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (0<<4); + case AMOVWD: return o | (0x0a<<24) | (1<<20) | (1<<6) | (0<<4); + case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0<<4); /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=1 */ - case AMOVDW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<6) | (1<<4); - case AMOVFW: return o | (0x0a<<24) | (1<<20) | (0xee<<8) | (1<<4); + case AMOVDW: return o | (0x0a<<24) | (1<<20) | (1<<6) | (1<<4); + case AMOVFW: return o | (0x0a<<24) | (1<<20) | (1<<4); /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1 */ - case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | (0xee<<8) | 0xb7; - case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | (0xee<<8) | 0xb7; + case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | 0xb7; + case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | 0xb7; /* VMOV (register) (ARMv7-M ARM, A7.7.237) */ - case AMOVD: return o | (0x0b<<24) | (0x40<<16) | (0xee<<8) | 0xb0; - case AMOVF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb0; + case AMOVF: return o | (0x0a<<24) | (0x40<<16) | 0xb0; + case AMOVD: return o | (0x0b<<24) | (0x40<<16) | 0xb0; /* VCMP (ARMv7-M ARM, A7.7.223), encoding T1 */ - case ACMPD: - case ACMPF: return o | (0x0a<<24) | (0x40<<16) | (0xee<<8) | 0xb4; + case ACMPF: return o | (0x0a<<24) | (0x40<<16) | 0xb4; + case ACMPD: return o | (0x0b<<24) | (0x40<<16) | 0xb4; /* arguably, ACMPF should expand to RNDF, CMPD */ /* VADD (ARMv7-M ARM, A7.7.222) */ - case AADDD: return o | (0x0b<<24) | (0xee<<8) | 0x30; - case AADDF: return o | (0x0a<<24) | (0xee<<8) | 0x30; + case AADDD: return o | (0x0b<<24) | 0x30; + case AADDF: return o | (0x0a<<24) | 0x30; /* VSUB (ARMv7-M ARM, A7.7.257) */ - case ASUBD: return o | (0x0b<<24) | (0x4<<20) | (0xee<<8) | 0x30; - case ASUBF: return o | (0x0a<<24) | (0x4<<20) | (0xee<<8) | 0x30; + case ASUBD: return o | (0x0b<<24) | (0x4<<20) | 0x30; + case ASUBF: return o | (0x0a<<24) | (0x4<<20) | 0x30; /* VMUL (ARMv7-M ARM, A7.7.245) */ - case AMULD: return o | (0x0b<<24) | (0xee<<8) | 0x20; - case AMULF: return o | (0x0a<<24) | (0xee<<8) | 0x20; + case AMULD: return o | (0x0b<<24) | 0x20; + case AMULF: return o | (0x0a<<24) | 0x20; /* VDIV (ARMv7-M ARM, A7.7.229) */ - case ADIVD: return o | (0x0b<<24) | (0xee<<8) | 0x80; - case ADIVF: return o | (0x0a<<24) | (0xee<<8) | 0x80; + case ADIVD: return o | (0x0b<<24) | 0x80; + case ADIVF: return o | (0x0a<<24) | 0x80; } diag("bad fp %d", a); prasm(curp); -- cgit v1.2.3 From 91cabfea314f504c5e5d62770bb74dc71193570a Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 11 Feb 2022 02:11:12 +0100 Subject: Added support for AND instruction variants. --- utils/tl/thumb.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index ed2943e0..69e0c5dd 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -346,7 +346,6 @@ Optab thumboptab[] = { AADD, C_SCON, C_REG, C_REG, 3, 2, 0 }, { AADD, C_LCON, C_REG, C_REG, 49, 4, 0 }, { AADD, C_GCON, C_REG, C_REG, 36, 4, 0, LFROM }, - // { AADD, C_LCON, C_NONE, C_REG, 3, 2, 0, LFROM }, { ASRL, C_SCON, C_REG, C_REG, 4, 2, 0 }, { ASRL, C_SCON, C_NONE, C_REG, 4, 2, 0 }, { AADD, C_SCON, C_NONE, C_REG, 5, 2, 0 }, @@ -357,6 +356,8 @@ 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 }, // { 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 }, @@ -526,7 +527,7 @@ Optab thumboptab[] = { AXXX, C_NONE, C_NONE, C_NONE, 0, 2, 0 }, }; -#define OPCNTSZ 61 +#define OPCNTSZ 62 int opcount[OPCNTSZ]; // is this too pessimistic ? @@ -1375,6 +1376,27 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); break; + + case 61: /* op $c, r */ + rt = p->to.reg; + if (p->reg == NREG) + r = rt; + else + r = p->reg; + + switch (p->as) { + case AAND: + o1 = 0x0000f000 | r | (rt<<24) | ((instoffset & 0xff)<<16) | + ((instoffset & 0x700) << 20) | + ((instoffset & 0x800) >> 1); + break; + default: + print("%A %d %d %d\n", p->as, instoffset, p->reg, p->to.reg); + diag("not implemented: %A", p->as); + break; + } + SPLIT_INS(o1, o2); + break; } v = p->pc; -- cgit v1.2.3 From 099dd430c543304921f6ba57934a430689b2cb4c Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 16 Feb 2022 23:48:58 +0100 Subject: Moved division and modulo operator support into the compiler. Fixed constant encoding in case 61. --- utils/tl/l.h | 7 -- utils/tl/noop.c | 227 ------------------------------------------------------- utils/tl/obj.c | 3 - utils/tl/pass.c | 4 - 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; -- cgit v1.2.3 From da381efbb790e33a14f8ff1c041a2ce5be315924 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 10 Dec 2022 01:42:47 +0100 Subject: Build the Thumb suite by default. Create a library directory for Thumb-native Inferno. --- lib/emptydirs | 1 + utils/mkfile | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/emptydirs b/lib/emptydirs index 10234dc1..d2f94c40 100644 --- a/lib/emptydirs +++ b/lib/emptydirs @@ -10,6 +10,7 @@ Inferno/power/bin Inferno/power/lib Inferno/sparc/bin Inferno/sparc/lib +Inferno/thumb/lib Irix/mips/lib Linux/386/lib Linux/arm/bin diff --git a/utils/mkfile b/utils/mkfile index 804215b3..e6ee371a 100644 --- a/utils/mkfile +++ b/utils/mkfile @@ -54,6 +54,9 @@ NOTPLAN9=\ md5sum\ mkext\ ndate\ + ta\ + tc\ + tl\ # # Utils we build on Nt, for build environment compatibility. @@ -76,9 +79,6 @@ NTONLY=\ # Thumb-1 # OBSOLETE=\ - ta\ - tc\ - tl\ all:QV: all-$TARGMODEL clean:QV: clean-$TARGMODEL -- cgit v1.2.3 From d8023f9f90be42752d6f61a1a436444f0cfad288 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sun, 2 Apr 2023 18:24:31 +0200 Subject: Imposed limitations on supported instruction encodings. --- utils/tl/thumb.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index f91b9d64..ff089918 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1407,9 +1407,24 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); diag("not implemented: %A", p->as); break; } - o1 |= r | (rt<<24) | ((instoffset & 0xff)<<16) | - ((instoffset & 0x700) << 20) | - ((instoffset & 0x800) >> 1); + + /* Only certain ranges of constants are supported. */ + if ((instoffset & 0xff) == instoffset) { + o1 |= r | (rt<<24) | (instoffset << 16); + } else if (((instoffset & 0xff00ff) == instoffset) && + ((instoffset & 0xff) == ((instoffset >> 16) & 0xff))) { + o1 |= r | (rt<<24) | ((instoffset & 0xff) << 16) | (1 << 28); + } else if (((instoffset & 0xff00ff00) == instoffset) && + (((instoffset >> 8) & 0xff) == ((instoffset >> 24) & 0xff))) { + o1 |= r | (rt<<24) | ((instoffset & 0xff) << 16) | (2 << 28); + } else if (((instoffset & 0xff) == ((instoffset >> 8) & 0xff)) && + ((instoffset & 0xff) == ((instoffset >> 16) & 0xff)) && + ((instoffset & 0xff) == ((instoffset >> 24) & 0xff))) { + o1 |= r | (rt<<24) | ((instoffset & 0xff) << 16) | (3 << 28); + } else { + print("%A %d %d %d\n", p->as, instoffset, p->reg, p->to.reg); + diag("constant not supported: %ux", instoffset); + } SPLIT_INS(o1, o2); break; -- cgit v1.2.3 From 691df57aba2063cba34cc3bcf0cea90a54e83e76 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sun, 2 Apr 2023 18:24:44 +0200 Subject: Enabled assembly of constant strings into the text segment. --- utils/tl/asm.c | 22 ++++++++++++++++------ utils/tl/l.h | 2 ++ utils/tl/span.c | 2 ++ utils/tl/thumb.c | 6 +++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/utils/tl/asm.c b/utils/tl/asm.c index 66a7f0c6..ec0f63a8 100644 --- a/utils/tl/asm.c +++ b/utils/tl/asm.c @@ -63,17 +63,15 @@ asmb(void) asmout(p, o); pc += o->size; } - while(pc-INITTEXT < textsize) { - cput(0); - pc++; + + /* output strings in text segment */ + while (pc < INITRODAT) { + cput(0); pc++; } - if(debug['a']) - Bprint(&bso, "\n"); Bflush(&bso); cflush(); - /* output strings in text segment */ etext = INITTEXT + textsize; for(t = pc; t < etext; t += sizeof(buf)-100) { if(etext-t > sizeof(buf)-100) @@ -82,6 +80,18 @@ asmb(void) datblk(t, etext-t, 1); } + pc = t; + + while(pc-INITTEXT < textsize) { + cput(0); + pc++; + } + + if(debug['a']) + Bprint(&bso, "\n"); + Bflush(&bso); + cflush(); + curtext = P; switch(HEADTYPE) { case 0: diff --git a/utils/tl/l.h b/utils/tl/l.h index f2e6ad02..3e84ff66 100644 --- a/utils/tl/l.h +++ b/utils/tl/l.h @@ -90,6 +90,7 @@ struct Sym uchar fnptr; // used as fn ptr Use* use; Sym* link; + long base; }; #define SIGNINTERN (1729*325*1729) @@ -248,6 +249,7 @@ EXTERN union EXTERN long HEADR; /* length of header */ EXTERN int HEADTYPE; /* type of header */ EXTERN long INITDAT; /* data location */ +EXTERN long INITRODAT; /* read-only data location */ EXTERN long INITRND; /* data round above text location */ EXTERN long INITTEXT; /* text location */ EXTERN char* INITENTRY; /* entry point */ diff --git a/utils/tl/span.c b/utils/tl/span.c index 8ceaf631..6d5a0443 100644 --- a/utils/tl/span.c +++ b/utils/tl/span.c @@ -350,6 +350,7 @@ span(void) * add strings to text segment */ c = rnd(c, 8); + INITRODAT = c; for(i=0; ilink) { if(s->type != SSTRING) @@ -358,6 +359,7 @@ span(void) while(v & 3) v++; s->value = c; + s->base = -INITDAT; // compensate for assumptions in thumb.c c += v; } } diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index ff089918..d3324ebf 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -181,7 +181,7 @@ thumbaclass(Adr *a, Prog *p) a->sym->name, TNAME); a->sym->type = SDATA; } - instoffset = a->sym->value + a->offset + INITDAT; + instoffset = a->sym->value + a->offset + INITDAT + a->sym->base; return C_LEXT; /* INITDAT unknown at this stage */ // return immacon(instoffset, p, C_SEXT, C_LEXT); case D_AUTO: @@ -213,7 +213,7 @@ thumbaclass(Adr *a, Prog *p) s->name, TNAME); s->type = SDATA; } - instoffset = s->value + a->offset + INITDAT; + instoffset = s->value + a->offset + INITDAT + s->base; if(s->type == STEXT || s->type == SLEAF){ instoffset = s->value + a->offset; #ifdef CALLEEBX @@ -262,7 +262,7 @@ thumbaclass(Adr *a, Prog *p) #endif return C_LCON; } - instoffset = s->value + a->offset + INITDAT; + instoffset = s->value + a->offset + INITDAT + s->base; return C_LCON; /* INITDAT unknown at this stage */ // return immcon(instoffset, p); case D_AUTO: -- cgit v1.2.3 From 86b2cf0334929ccee3cb492e043bd7722b4f439c Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 9 Sep 2023 19:15:53 +0200 Subject: Added a note about the number of floating point registers. Hopefully fix float-int transfer and comparison instructions. --- utils/tc/5.out.h | 4 ++-- utils/tl/thumb.c | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/utils/tc/5.out.h b/utils/tc/5.out.h index 59aebab6..3d599ac0 100644 --- a/utils/tc/5.out.h +++ b/utils/tc/5.out.h @@ -18,8 +18,8 @@ #define REGSP 13 #define REGLINK 14 #define REGPC 15 - -#define NFREG 8 + +#define NFREG 8 /* number of double precision registers */ #define FREGRET 0 #define FREGEXT 7 /* compiler allocates register variables F0 up */ diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index d3324ebf..4b737756 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1345,9 +1345,10 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); rf = p->from.reg; rt = p->reg; - /* VCMP (ARMv7-M ARM, A7.7.223) */ - o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21) | /* Vm */ - ((r & 0x1e)<<27) | ((r & 1)<<6); /* Vd */ + if (rf != 16) // VCMP (ARMv7-M ARM, A7.7.223, T1) + o1 |= ((rf & 0x0f)<<16) | ((r & 0x0f)<<28); /* Vm, Vd */ + else // VCMP (ARMv7-M ARM, A7.7.223, T2) compare to 0.0 + o1 |= ((r & 0x0f) << 28) | 0x1; /* VMRS (ARMv7-M ARM, A7.7.243) with Rt=15 (for flags) */ o3 = 0x0a10eef1 | (15 << 28); @@ -1665,15 +1666,17 @@ thumbopfp(int a, int sc) { long o = 0; - o |= 0xee << 8; + o |= 0xee00; // Prepare the first half-word in the sequence. switch(a) { /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=0 */ - case AMOVWD: return o | (0x0a<<24) | (1<<20) | (1<<6) | (0<<4); case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0<<4); /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=1 */ - case AMOVDW: return o | (0x0a<<24) | (1<<20) | (1<<6) | (1<<4); case AMOVFW: return o | (0x0a<<24) | (1<<20) | (1<<4); + /* VMOV (ARMv7-M ARM, A7.7.242), encoding T1, op=0 */ + case AMOVWD: return o | (0x0b<<24) | (1<<20) | (1<<6) | (0<<4); + /* VMOV (ARMv7-M ARM, A7.7.242), encoding T1, op=1 */ + case AMOVDW: return o | (0x0b<<24) | (1<<20) | (1<<6) | (1<<4); /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1 */ case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | 0xb7; case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | 0xb7; -- cgit v1.2.3 From 672743883393cfd5bdccf82cc8f5d83c0870cc16 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 11 Sep 2023 19:05:00 +0200 Subject: Fixed register encoding, or at least made our use of registers consistent. --- utils/tl/thumb.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 4b737756..98db008e 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1306,9 +1306,9 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); case AMULD: case ASUBF: case ASUBD: - o1 |= (r >> 1) | ((r & 1) << 23) | /* Vn */ - ((rf & 0x1e)<<15) | ((rf & 1)<<21) | /* Vm */ - ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + o1 |= (r & 0xf) | /* Vn */ + ((rf & 0xf)<<16) | /* Vm */ + ((rt & 0xf)<<28); /* Vd */ break; case AMOVF: case AMOVD: /* TODO: actually use double precision */ @@ -1317,8 +1317,8 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); /* Float constant was zero */ /* VSUB rt, rt, rt (ARMv7-M ARM, A7.7.257) */ o1 ^= 1 << 7; - o1 |= (rt >> 1) | ((rt & 1) << 23); /* Vn */ - o1 |= ((rt & 0x1e)<<15) | ((rt & 1)<<21); /* Vm */ + o1 |= (rt & 0xf); /* Vn */ + o1 |= ((rt & 0xf)<<16); /* Vm */ } else { /* VMOV immediate (ARMv7-M ARM, A7.7.236) */ o1 ^= 1 << 22; @@ -1326,9 +1326,9 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); } } else { /* VMOV register (ARMv7-M ARM, A7.7.237) */ - o1 |= ((rf & 0x1e)<<15) | ((rf & 1)<<21); /* Vm */ + o1 |= ((rf & 0xf)<<16); /* Vm */ } - o1 |= ((rt & 0x1e)<<27) | ((rt & 1)<<6); /* Vd */ + o1 |= ((rt & 0xf)<<28); /* Vd */ if (p->as == AMOVD) o1 |= 1 << 24; break; @@ -1720,9 +1720,9 @@ thumbofsr(int a, int r, long v, int b, Prog *p) diag("odd offset for floating point op: %d\n%P", v, p); else if(v >= (1<<10)) diag("literal span too large: %d\n%P", v, p); - o |= ((v>>2) & 0xFF) << 16; /* offset */ - o |= b; /* Rn */ - o |= ((r & 0x1e) << 27) | ((r & 1) << 6); /* Vd */ + o |= ((v>>2) & 0xFF) << 16; /* offset */ + o |= b; /* Rn */ + o |= ((r & 0x0f) << 28); /* Vd */ switch(a) { default: -- cgit v1.2.3 From 3cbc2622cf597a1d066793a87b7a6a22a2da4294 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 12 Sep 2023 00:57:43 +0200 Subject: Adjusted transfers between doubles and register pairs. --- utils/tl/thumb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 98db008e..0143d7d0 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1357,7 +1357,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); SPLIT_INS(o3, o4); break; - case 58: /* floating point fix and float */ + case 58: /* floating point fix and float (MOVDW/MOVWD) */ o1 = thumbopfp(p->as, p->scond); rf = p->from.reg; rt = p->to.reg; @@ -1365,10 +1365,11 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); rt = 0; diag("to.type==D_NONE (asm/fp)"); } + // ### Check that this use of register pairs is valid. if(p->from.type == D_REG) - o1 |= (rf<<28) | ((rt & 1)<<23) | ((rt & 0x1e)>>1); + o1 |= ((rt & 0x0f)<<16) | ((rf & 0x0f)<<28) | ((rf+1) & 0x0f); else - o1 |= (rt<<28) | ((rf & 1)<<23) | ((rf & 0x1e)>>1); + o1 |= ((rf & 0x0f)<<16) | ((rt & 0x0f)<<28) | ((rt+1) & 0x0f); SPLIT_INS(o1, o2); break; -- cgit v1.2.3 From 303f0b0be6d00eb77532681708663c94beb45d86 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 16 Nov 2023 15:56:33 +0100 Subject: Made single and double FP register usage consistent. Worked around double to long handling in the _d2l function. --- libkern/vlrt-thumb.c | 10 +++++++--- utils/tl/thumb.c | 35 ++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/libkern/vlrt-thumb.c b/libkern/vlrt-thumb.c index 58cf5591..e94ec2de 100644 --- a/libkern/vlrt-thumb.c +++ b/libkern/vlrt-thumb.c @@ -26,6 +26,12 @@ struct Vlong }; }; +struct RVlong +{ + ulong lo; + ulong hi; +}; + void abort(void); void @@ -54,14 +60,12 @@ _subv(Vlong *r, Vlong a, Vlong b) r->hi = hi; } - void _d2v(Vlong *y, double d) { - union { double d; struct Vlong; } x; + union { double d; struct RVlong; } x; ulong xhi, xlo, ylo, yhi; int sh; - x.d = d; xhi = (x.hi & 0xfffff) | 0x100000; diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 0143d7d0..785dccf1 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1299,13 +1299,17 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); switch (p->as) { case AADDF: - case AADDD: case ADIVF: - case ADIVD: case AMULF: - case AMULD: case ASUBF: - case ASUBD: +// o1 |= ((r >> 1) & 0xf) | ((r & 1) << 23) | /* Vn */ +// (((rf >> 1) & 0xf)<<16) | ((rf & 1) << 21) | /* Vm */ +// (((rt >> 1) & 0xf)<<28) | ((rt & 1) << 6); /* Vd */ +// break; + case AADDD: + case ADIVD: + case AMULD: + case ASUBD: // assume that NFREG < 16 o1 |= (r & 0xf) | /* Vn */ ((rf & 0xf)<<16) | /* Vm */ ((rt & 0xf)<<28); /* Vd */ @@ -1345,7 +1349,7 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); rf = p->from.reg; rt = p->reg; - if (rf != 16) // VCMP (ARMv7-M ARM, A7.7.223, T1) + if (rf != NREG) // VCMP (ARMv7-M ARM, A7.7.223, T1) o1 |= ((rf & 0x0f)<<16) | ((r & 0x0f)<<28); /* Vm, Vd */ else // VCMP (ARMv7-M ARM, A7.7.223, T2) compare to 0.0 o1 |= ((r & 0x0f) << 28) | 0x1; @@ -1365,11 +1369,20 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); rt = 0; diag("to.type==D_NONE (asm/fp)"); } - // ### Check that this use of register pairs is valid. - if(p->from.type == D_REG) - o1 |= ((rt & 0x0f)<<16) | ((rf & 0x0f)<<28) | ((rf+1) & 0x0f); - else - o1 |= ((rf & 0x0f)<<16) | ((rt & 0x0f)<<28) | ((rt+1) & 0x0f); + if ((p->as == AMOVWD) || (p->as == AMOVDW)) { + // ### Check that this use of register pairs is valid. + if(p->from.type == D_REG) + o1 |= ((rt & 0x0f)<<16) | ((rf & 0x0f)<<28) | ((rf+1) & 0x0f); + else + o1 |= ((rf & 0x0f)<<16) | ((rt & 0x0f)<<28) | ((rt+1) & 0x0f); + + } else if (p->as == AMOVDF) { + // Vd:D M:Vm - only support 16 registers + o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 27) | ((rf & 0x0f) << 16); + } else { + // MOVFD: D:Vd Vm:M - only support 16 registers + o1 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); + } SPLIT_INS(o1, o2); break; @@ -1678,7 +1691,7 @@ thumbopfp(int a, int sc) case AMOVWD: return o | (0x0b<<24) | (1<<20) | (1<<6) | (0<<4); /* VMOV (ARMv7-M ARM, A7.7.242), encoding T1, op=1 */ case AMOVDW: return o | (0x0b<<24) | (1<<20) | (1<<6) | (1<<4); - /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1 */ + /* VCVT (ARMv7-M ARM, A7.7.227), encoding T1 */ case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | 0xb7; case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | 0xb7; /* VMOV (register) (ARMv7-M ARM, A7.7.237) */ -- cgit v1.2.3 From b5ffd12d6aeb8c977cfefb0da5f569422b84ee5e Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 15 Sep 2023 12:53:17 +0200 Subject: Unsuccessfully tried to implement reasonable sets of instructions. --- utils/tl/thumb.c | 77 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 785dccf1..51d13d83 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -515,10 +515,10 @@ Optab thumboptab[] = { ACMPD, C_FREG, C_REG, C_NONE, 57, 8, 0 }, { ACMPD, C_FCON, C_REG, C_NONE, 57, 8, 0 }, - { AMOVFW, C_FREG, C_NONE, C_REG, 58, 4, 0 }, - { AMOVWF, C_REG, C_NONE, C_FREG, 58, 4, 0 }, - { AMOVWD, C_REG, C_NONE, C_FREG, 58, 4, 0 }, - { AMOVDW, C_FREG, C_NONE, C_REG, 58, 4, 0 }, + { AMOVFW, C_FREG, C_NONE, C_REG, 58, 8, 0 }, + { AMOVWF, C_REG, C_NONE, C_FREG, 58, 8, 0 }, + { AMOVWD, C_REG, C_NONE, C_FREG, 58, 12, 0 }, + { AMOVDW, C_FREG, C_NONE, C_REG, 58, 12, 0 }, { AMOVFD, C_FREG, C_NONE, C_FREG, 58, 4, 0 }, { AMOVDF, C_FREG, C_NONE, C_FREG, 58, 4, 0 }, @@ -1362,28 +1362,69 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 58: /* floating point fix and float (MOVDW/MOVWD) */ - o1 = thumbopfp(p->as, p->scond); rf = p->from.reg; rt = p->to.reg; if(p->to.type == D_NONE){ rt = 0; diag("to.type==D_NONE (asm/fp)"); } - if ((p->as == AMOVWD) || (p->as == AMOVDW)) { - // ### Check that this use of register pairs is valid. - if(p->from.type == D_REG) - o1 |= ((rt & 0x0f)<<16) | ((rf & 0x0f)<<28) | ((rf+1) & 0x0f); - else - o1 |= ((rf & 0x0f)<<16) | ((rt & 0x0f)<<28) | ((rt+1) & 0x0f); - - } else if (p->as == AMOVDF) { - // Vd:D M:Vm - only support 16 registers - o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 27) | ((rf & 0x0f) << 16); + if ((p->as == AMOVWD) || (p->as == AMOVWF)) { + /* Transfer the contents of the register then convert it + to a floating point representation. */ + // VMOV A7.7.240 + o1 = 0x0a10ee00; + o1 |= ((rt & 1) << 23) | (rt >> 1); /* Fd */ + o1 |= (rf << 28); /* Rm */ + + // VCVT (A7.7.225) - note invalid opc2 bits in manual + // op=0, Fd=Fm=rt + o3 = 0x0a40feb8; + o3 |= 1; // signed + o3 |= ((rt & 1) << 21) | ((rt & 0xe) << 16); /* Fm */ + o3 |= ((rt & 1) << 6) | ((rt & 0xe) << 28); /* Fd */ + + SPLIT_INS(o1, o2); + SPLIT_INS(o3, o4); + + if (p->as == AMOVWD) { + o5 = thumbopfp(AMOVFD, p->scond); + o5 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); + SPLIT_INS(o5, o6); + } + } else if ((p->as == AMOVDW) || (p->as == AMOVFW)) { + /* Convert the floating point representation of the number + to an integer then transfer the contents to a register. */ + // VCVT (A7.7.225) - note invalid opc2 bits in manual + // op=0, Fd=Fm=rt + o1 = 0x0a40feb8; + o1 |= 4; // to integer + o1 |= 1; // signed + o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 28); /* Fd */ + if (p->as == AMOVDW) + o1 |= ((rt & 0xf) << 28) | 0x01000000; /* Fm */ + else + o1 |= ((rt & 1) << 21) | ((rt & 0xe) << 16);/* Fm */ + + // VMOV A7.7.240 + o3 = 0x0a10ee00 | 0x10; + o3 |= ((rf & 1) << 23) | (rf >> 1); + o3 |= (rt << 28); + SPLIT_INS(o1, o2); + SPLIT_INS(o3, o4); } else { - // MOVFD: D:Vd Vm:M - only support 16 registers - o1 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); + o1 = thumbopfp(p->as, p->scond); + if (p->as == AMOVDF) { + // Vd:D M:Vm - only support 16 registers + o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 27) | ((rf & 0x0f) << 16); + } else if (p->as == AMOVFD) { + // MOVFD: D:Vd Vm:M - only support 16 registers + o1 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); + } else + diag("unhandled case 58"); + + SPLIT_INS(o1, o2); } - SPLIT_INS(o1, o2); + break; case 59: /* move to FP[CS]R */ -- cgit v1.2.3 From 9d9206bbe07886f40dda30046114d847a52bde1e Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 16 Nov 2023 16:03:12 +0100 Subject: Used modified VFP instruction sequences from 5l. --- utils/tl/thumb.c | 105 +++++++++++++++++++++---------------------------------- 1 file changed, 40 insertions(+), 65 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 51d13d83..6473675e 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -517,8 +517,8 @@ Optab thumboptab[] = { AMOVFW, C_FREG, C_NONE, C_REG, 58, 8, 0 }, { AMOVWF, C_REG, C_NONE, C_FREG, 58, 8, 0 }, - { AMOVWD, C_REG, C_NONE, C_FREG, 58, 12, 0 }, - { AMOVDW, C_FREG, C_NONE, C_REG, 58, 12, 0 }, + { AMOVWD, C_REG, C_NONE, C_FREG, 58, 8, 0 }, + { AMOVDW, C_FREG, C_NONE, C_REG, 58, 8, 0 }, { AMOVFD, C_FREG, C_NONE, C_FREG, 58, 4, 0 }, { AMOVDF, C_FREG, C_NONE, C_FREG, 58, 4, 0 }, @@ -1362,69 +1362,43 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; case 58: /* floating point fix and float (MOVDW/MOVWD) */ + o1 = thumbopfp(p->as, p->scond); rf = p->from.reg; rt = p->to.reg; - if(p->to.type == D_NONE){ - rt = 0; - diag("to.type==D_NONE (asm/fp)"); - } - if ((p->as == AMOVWD) || (p->as == AMOVWF)) { - /* Transfer the contents of the register then convert it - to a floating point representation. */ - // VMOV A7.7.240 - o1 = 0x0a10ee00; - o1 |= ((rt & 1) << 23) | (rt >> 1); /* Fd */ - o1 |= (rf << 28); /* Rm */ - - // VCVT (A7.7.225) - note invalid opc2 bits in manual - // op=0, Fd=Fm=rt - o3 = 0x0a40feb8; - o3 |= 1; // signed - o3 |= ((rt & 1) << 21) | ((rt & 0xe) << 16); /* Fm */ - o3 |= ((rt & 1) << 6) | ((rt & 0xe) << 28); /* Fd */ + if (p->as == AMOVDF) { + // Vd:D M:Vm - only support 16 registers + o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 27) | ((rf & 0x0f) << 16); SPLIT_INS(o1, o2); - SPLIT_INS(o3, o4); - - if (p->as == AMOVWD) { - o5 = thumbopfp(AMOVFD, p->scond); - o5 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); - SPLIT_INS(o5, o6); - } - } else if ((p->as == AMOVDW) || (p->as == AMOVFW)) { - /* Convert the floating point representation of the number - to an integer then transfer the contents to a register. */ - // VCVT (A7.7.225) - note invalid opc2 bits in manual - // op=0, Fd=Fm=rt - o1 = 0x0a40feb8; - o1 |= 4; // to integer - o1 |= 1; // signed - o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 28); /* Fd */ - if (p->as == AMOVDW) - o1 |= ((rt & 0xf) << 28) | 0x01000000; /* Fm */ - else - o1 |= ((rt & 1) << 21) | ((rt & 0xe) << 16);/* Fm */ - - // VMOV A7.7.240 - o3 = 0x0a10ee00 | 0x10; - o3 |= ((rf & 1) << 23) | (rf >> 1); - o3 |= (rt << 28); + } else if (p->as == AMOVFD) { + // MOVFD: D:Vd Vm:M - only support 16 registers + o1 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); SPLIT_INS(o1, o2); - SPLIT_INS(o3, o4); } else { - o1 = thumbopfp(p->as, p->scond); - if (p->as == AMOVDF) { - // Vd:D M:Vm - only support 16 registers - o1 |= ((rt & 1) << 6) | ((rt & 0xe) << 27) | ((rf & 0x0f) << 16); - } else if (p->as == AMOVFD) { - // MOVFD: D:Vd Vm:M - only support 16 registers - o1 |= ((rt & 0x0f)<<28) | ((rf & 1) << 21) | ((rf & 0x0e) << 16); - } else - diag("unhandled case 58"); - + if (p->from.type == D_REG) { // int -> float + // VCVT (A7.7.225) + o3 = o1 | (rt << 16); // Vm:M (*2 to align with doubles) + if (p->as == AMOVWD) + o3 |= rt << 28; // D:Vd + else + o3 |= ((rt >> 1) << 28) | ((rt & 1) << 6); // Vd:D + // VMOV F,R (A7.7.240) + o1 = 0x0a10ee00; + o1 |= rt | rf<<28; // rt = Vn:N (*2 to align with doubles) + } else { // float -> int + // VCVT (A7.7.225) rf -> FREGTMP + o1 |= FREGTMP<<28; // Vd:D + if (p->as == AMOVDW) + o1 |= rf << 16; // M:Vm + else + o1 |= ((rf & 1) << 21) | ((rf >> 1) << 16); // Vm:M + // VMOV R,F (A7.7.240) FREFTMP -> rt + o3 = 0x0a10ee10; + o3 |= FREGTMP | rt<<28; + } SPLIT_INS(o1, o2); + SPLIT_INS(o3, o4); } - break; case 59: /* move to FP[CS]R */ @@ -1719,19 +1693,20 @@ thumboprrr(int a, int ld) long thumbopfp(int a, int sc) { + /* See opvfprrr in 5l/asm.c for hints. */ long o = 0; o |= 0xee00; // Prepare the first half-word in the sequence. switch(a) { - /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=0 */ - case AMOVWF: return o | (0x0a<<24) | (1<<20) | (0<<4); - /* VMOV (ARMv7-M ARM, A7.7.240), encoding T1, op=1 */ - case AMOVFW: return o | (0x0a<<24) | (1<<20) | (1<<4); - /* VMOV (ARMv7-M ARM, A7.7.242), encoding T1, op=0 */ - case AMOVWD: return o | (0x0b<<24) | (1<<20) | (1<<6) | (0<<4); - /* VMOV (ARMv7-M ARM, A7.7.242), encoding T1, op=1 */ - case AMOVDW: return o | (0x0b<<24) | (1<<20) | (1<<6) | (1<<4); + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ + case AMOVWF: return o | (0x0a << 24) | (0xc0 << 16) | 0xb8; + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ + case AMOVFW: return o | (0x0a << 24) | (0xc0 << 16) | 0xbd; + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ + case AMOVWD: return o | (0x0b << 24) | (0xc0 << 16) | 0xb8; + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ + case AMOVDW: return o | (0x0b << 24) | (0xc0 << 16) | 0xbd; /* VCVT (ARMv7-M ARM, A7.7.227), encoding T1 */ case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | 0xb7; case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | 0xb7; -- cgit v1.2.3 From 7c8dbb930032aa3eae11d95f7f2f1afff16859e9 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sun, 17 Sep 2023 16:43:56 +0200 Subject: Adapted code from 5l to simplify the FP comparison case. Annotated the integer/float conversion encodings. --- utils/tl/thumb.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 6473675e..0c568a37 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1349,10 +1349,16 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); rf = p->from.reg; rt = p->reg; - if (rf != NREG) // VCMP (ARMv7-M ARM, A7.7.223, T1) - o1 |= ((rf & 0x0f)<<16) | ((r & 0x0f)<<28); /* Vm, Vd */ - else // VCMP (ARMv7-M ARM, A7.7.223, T2) compare to 0.0 - o1 |= ((r & 0x0f) << 28) | 0x1; + if(p->from.type == D_FCONST) { + if(p->from.ieee->h != 0 || p->from.ieee->l != 0) + diag("invalid floating-point immediate\n%P", p); + // VCMP (ARMv7-M ARM, A7.7.223, T2) compare to 0.0 + o1 |= 1; + rf = 0; + } + + // VCMP (ARMv7-M ARM, A7.7.223, T1) + o1 |= ((rf & 0x0f)<<16) | ((rt & 0x0f)<<28); /* Vm, Vd */ /* VMRS (ARMv7-M ARM, A7.7.243) with Rt=15 (for flags) */ o3 = 0x0a10eef1 | (15 << 28); @@ -1698,15 +1704,21 @@ thumbopfp(int a, int sc) o |= 0xee00; // Prepare the first half-word in the sequence. + // VCVT opc2 bits are to_int,0,signed + switch(a) { - /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ - case AMOVWF: return o | (0x0a << 24) | (0xc0 << 16) | 0xb8; - /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ - case AMOVFW: return o | (0x0a << 24) | (0xc0 << 16) | 0xbd; - /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ - case AMOVWD: return o | (0x0b << 24) | (0xc0 << 16) | 0xb8; - /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1 */ - case AMOVDW: return o | (0x0b << 24) | (0xc0 << 16) | 0xbd; + case AMOVWF: + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1, sz=0, opc2=b_000 */ + return o | (0x0a << 24) | (0xc0 << 16) | 0xb8; + case AMOVFW: + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1, sz=0, opc2=b_101 */ + return o | (0x0a << 24) | (0xc0 << 16) | 0xbd; + case AMOVWD: + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1, sz=1, opc2=b_000 */ + return o | (0x0b << 24) | (0xc0 << 16) | 0xb8; + case AMOVDW: + /* VCVT (ARMv7-M ARM, A7.7.225), encoding T1, op=1, sz=1, opc2=b_101 */ + return o | (0x0b << 24) | (0xc0 << 16) | 0xbd; /* VCVT (ARMv7-M ARM, A7.7.227), encoding T1 */ case AMOVFD: return o | (0x0a<<24) | (0xc0<<16) | 0xb7; case AMOVDF: return o | (0x0b<<24) | (0xc0<<16) | 0xb7; -- cgit v1.2.3 From 5e73ed63cfea68deef9943f2646c4c65c2dc3e73 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 22 Sep 2023 22:15:37 +0200 Subject: Reassigned the temporary floating point register. --- utils/5c/5.out.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/5c/5.out.h b/utils/5c/5.out.h index a618f8f1..667456e0 100644 --- a/utils/5c/5.out.h +++ b/utils/5c/5.out.h @@ -25,7 +25,7 @@ #define NFREG 8 #define FREGRET 0 #define FREGEXT 7 -#define FREGTMP 15 +#define FREGTMP 7 /* compiler allocates register variables F0 up */ /* compiler allocates external registers F7 down */ -- cgit v1.2.3 From d8e1ae57f2200bc539f63848c790867788b2e133 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sun, 24 Sep 2023 17:53:38 +0200 Subject: Added a definition for the temporary floating point register. --- utils/tc/5.out.h | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/tc/5.out.h b/utils/tc/5.out.h index 3d599ac0..7a35f1c2 100644 --- a/utils/tc/5.out.h +++ b/utils/tc/5.out.h @@ -22,6 +22,7 @@ #define NFREG 8 /* number of double precision registers */ #define FREGRET 0 #define FREGEXT 7 +#define FREGTMP 7 /* compiler allocates register variables F0 up */ /* compiler allocates external registers F7 down */ -- cgit v1.2.3 From 1b44446e0d632d96dfba82c401b0aa12a1dfc00a Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 16 Nov 2023 00:58:13 +0100 Subject: Fixed support for the status flag in some AND instructions. --- utils/tl/thumb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/tl/thumb.c b/utils/tl/thumb.c index 0c568a37..a309f82b 100644 --- a/utils/tl/thumb.c +++ b/utils/tl/thumb.c @@ -1444,6 +1444,9 @@ if(debug['G']) print("%ulx: %s: thumb\n", (ulong)(p->pc), p->from.sym->name); break; } + if (p->scond & C_SBIT) + o1 |= (1 << 4); + /* Only certain ranges of constants are supported. */ if ((instoffset & 0xff) == instoffset) { o1 |= r | (rt<<24) | (instoffset << 16); -- cgit v1.2.3