summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/tl/thumb.c77
1 files 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 */