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