diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/tl/thumb.c | 77 |
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 */ |
