summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Boddie <david@boddie.org.uk>2023-11-16 15:56:33 +0100
committerDavid Boddie <david@boddie.org.uk>2023-11-16 16:44:28 +0100
commit303f0b0be6d00eb77532681708663c94beb45d86 (patch)
tree74adc7e5baa4eedbf6a1c27dccef481e0cec3968
parent3cbc2622cf597a1d066793a87b7a6a22a2da4294 (diff)
Made single and double FP register usage consistent.
Worked around double to long handling in the _d2l function.
-rw-r--r--libkern/vlrt-thumb.c10
-rw-r--r--utils/tl/thumb.c35
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) */