2 /*---------------------------------------------------------------*/
3 /*--- begin host_arm_defs.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "libvex_basictypes.h"
33 #include "libvex_trc_values.h"
35 #include "main_util.h"
36 #include "host_generic_regs.h"
37 #include "host_arm_defs.h"
41 /* --------- Registers. --------- */
43 /* The usual HReg abstraction.
44 There are 16 general purpose regs.
47 void ppHRegARM ( HReg reg ) {
49 /* Be generic for all virtual regs. */
50 if (hregIsVirtual(reg)) {
54 /* But specific for real regs. */
55 switch (hregClass(reg)) {
58 vassert(r >= 0 && r < 16);
63 vassert(r >= 0 && r < 16);
68 vassert(r >= 0 && r < 32);
76 HReg hregARM_R0 ( void ) { return mkHReg(0, HRcInt32, False); }
77 HReg hregARM_R1 ( void ) { return mkHReg(1, HRcInt32, False); }
78 HReg hregARM_R2 ( void ) { return mkHReg(2, HRcInt32, False); }
79 HReg hregARM_R3 ( void ) { return mkHReg(3, HRcInt32, False); }
80 HReg hregARM_R4 ( void ) { return mkHReg(4, HRcInt32, False); }
81 HReg hregARM_R5 ( void ) { return mkHReg(5, HRcInt32, False); }
82 HReg hregARM_R6 ( void ) { return mkHReg(6, HRcInt32, False); }
83 HReg hregARM_R7 ( void ) { return mkHReg(7, HRcInt32, False); }
84 HReg hregARM_R8 ( void ) { return mkHReg(8, HRcInt32, False); }
85 HReg hregARM_R9 ( void ) { return mkHReg(9, HRcInt32, False); }
86 HReg hregARM_R10 ( void ) { return mkHReg(10, HRcInt32, False); }
87 HReg hregARM_R11 ( void ) { return mkHReg(11, HRcInt32, False); }
88 HReg hregARM_R12 ( void ) { return mkHReg(12, HRcInt32, False); }
89 HReg hregARM_R13 ( void ) { return mkHReg(13, HRcInt32, False); }
90 HReg hregARM_R14 ( void ) { return mkHReg(14, HRcInt32, False); }
91 HReg hregARM_R15 ( void ) { return mkHReg(15, HRcInt32, False); }
92 HReg hregARM_D8 ( void ) { return mkHReg(8, HRcFlt64, False); }
93 HReg hregARM_D9 ( void ) { return mkHReg(9, HRcFlt64, False); }
94 HReg hregARM_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
95 HReg hregARM_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
96 HReg hregARM_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
97 HReg hregARM_S26 ( void ) { return mkHReg(26, HRcFlt32, False); }
98 HReg hregARM_S27 ( void ) { return mkHReg(27, HRcFlt32, False); }
99 HReg hregARM_S28 ( void ) { return mkHReg(28, HRcFlt32, False); }
100 HReg hregARM_S29 ( void ) { return mkHReg(29, HRcFlt32, False); }
101 HReg hregARM_S30 ( void ) { return mkHReg(30, HRcFlt32, False); }
103 void getAllocableRegs_ARM ( Int* nregs, HReg** arr )
107 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
108 // callee saves ones are listed first, since we prefer them
109 // if they're available
110 (*arr)[i++] = hregARM_R4();
111 (*arr)[i++] = hregARM_R5();
112 (*arr)[i++] = hregARM_R6();
113 (*arr)[i++] = hregARM_R7();
114 (*arr)[i++] = hregARM_R10();
115 (*arr)[i++] = hregARM_R11();
116 // otherwise we'll have to slum it out with caller-saves ones
117 (*arr)[i++] = hregARM_R0();
118 (*arr)[i++] = hregARM_R1();
119 (*arr)[i++] = hregARM_R2();
120 (*arr)[i++] = hregARM_R3();
121 (*arr)[i++] = hregARM_R9();
122 // FP hreegisters. Note: these are all callee-save. Yay!
123 // Hence we don't need to mention them as trashed in
124 // getHRegUsage for ARMInstr_Call.
125 (*arr)[i++] = hregARM_D8();
126 (*arr)[i++] = hregARM_D9();
127 (*arr)[i++] = hregARM_D10();
128 (*arr)[i++] = hregARM_D11();
129 (*arr)[i++] = hregARM_D12();
130 (*arr)[i++] = hregARM_S26();
131 (*arr)[i++] = hregARM_S27();
132 (*arr)[i++] = hregARM_S28();
133 (*arr)[i++] = hregARM_S29();
134 (*arr)[i++] = hregARM_S30();
135 // unavail: r8 as GSP
136 // r12 'cos we're not sure what it's for
141 // All in all, we have 11 allocatable integer registers:
142 // 0 1 2 3 4 5 6 7 9 10 11 plus r8 dedicated as GSP.
143 // 12 13 14 and 15 are not under the allocator's control.
145 // Hence for the allocatable registers we have:
147 // callee-saved: 4 5 6 7 (8) 9 10 11
148 // caller-saved: 0 1 2 3
149 // Note 9 is ambiguous: the base EABI does not give an e/r-saved
150 // designation for it, but the Linux instantiation of the ABI
151 // specifies it as callee-saved.
153 // If the set of available registers changes or if the e/r status
154 // changes, be sure to re-check/sync the definition of
155 // getHRegUsage for ARMInstr_Call too.
156 vassert(i == *nregs);
161 /* --------- Condition codes, ARM encoding. --------- */
163 HChar* showARMCondCode ( ARMCondCode cond ) {
165 case ARMcc_EQ: return "eq";
166 case ARMcc_NE: return "ne";
167 case ARMcc_HS: return "hs";
168 case ARMcc_LO: return "lo";
169 case ARMcc_MI: return "mi";
170 case ARMcc_PL: return "pl";
171 case ARMcc_VS: return "vs";
172 case ARMcc_VC: return "vc";
173 case ARMcc_HI: return "hi";
174 case ARMcc_LS: return "ls";
175 case ARMcc_GE: return "ge";
176 case ARMcc_LT: return "lt";
177 case ARMcc_GT: return "gt";
178 case ARMcc_LE: return "le";
179 case ARMcc_AL: return "al"; // default
180 case ARMcc_NV: return "nv";
181 default: vpanic("showARMCondCode");
186 /* --------- Mem AModes: Addressing Mode 1 --------- */
188 ARMAMode1* ARMAMode1_RI ( HReg reg, Int simm13 ) {
189 ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
191 am->ARMam1.RI.reg = reg;
192 am->ARMam1.RI.simm13 = simm13;
193 vassert(-4095 <= simm13 && simm13 <= 4095);
196 ARMAMode1* ARMAMode1_RRS ( HReg base, HReg index, UInt shift ) {
197 ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
198 am->tag = ARMam1_RRS;
199 am->ARMam1.RRS.base = base;
200 am->ARMam1.RRS.index = index;
201 am->ARMam1.RRS.shift = shift;
202 vassert(0 <= shift && shift <= 3);
206 void ppARMAMode1 ( ARMAMode1* am ) {
209 vex_printf("%d(", am->ARMam1.RI.simm13);
210 ppHRegARM(am->ARMam1.RI.reg);
215 ppHRegARM(am->ARMam1.RRS.base);
217 ppHRegARM(am->ARMam1.RRS.index);
218 vex_printf(",%u)", am->ARMam1.RRS.shift);
225 static void addRegUsage_ARMAMode1 ( HRegUsage* u, ARMAMode1* am ) {
228 addHRegUse(u, HRmRead, am->ARMam1.RI.reg);
231 // addHRegUse(u, HRmRead, am->ARMam1.RRS.base);
232 // addHRegUse(u, HRmRead, am->ARMam1.RRS.index);
235 vpanic("addRegUsage_ARMAmode1");
239 static void mapRegs_ARMAMode1 ( HRegRemap* m, ARMAMode1* am ) {
242 am->ARMam1.RI.reg = lookupHRegRemap(m, am->ARMam1.RI.reg);
245 //am->ARMam1.RR.base =lookupHRegRemap(m, am->ARMam1.RR.base);
246 //am->ARMam1.RR.index = lookupHRegRemap(m, am->ARMam1.RR.index);
249 vpanic("mapRegs_ARMAmode1");
254 /* --------- Mem AModes: Addressing Mode 2 --------- */
256 ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 ) {
257 ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
259 am->ARMam2.RI.reg = reg;
260 am->ARMam2.RI.simm9 = simm9;
261 vassert(-255 <= simm9 && simm9 <= 255);
264 ARMAMode2* ARMAMode2_RR ( HReg base, HReg index ) {
265 ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
267 am->ARMam2.RR.base = base;
268 am->ARMam2.RR.index = index;
272 void ppARMAMode2 ( ARMAMode2* am ) {
275 vex_printf("%d(", am->ARMam2.RI.simm9);
276 ppHRegARM(am->ARMam2.RI.reg);
281 ppHRegARM(am->ARMam2.RR.base);
283 ppHRegARM(am->ARMam2.RR.index);
291 static void addRegUsage_ARMAMode2 ( HRegUsage* u, ARMAMode2* am ) {
294 addHRegUse(u, HRmRead, am->ARMam2.RI.reg);
297 // addHRegUse(u, HRmRead, am->ARMam2.RR.base);
298 // addHRegUse(u, HRmRead, am->ARMam2.RR.index);
301 vpanic("addRegUsage_ARMAmode2");
305 static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode2* am ) {
308 am->ARMam2.RI.reg = lookupHRegRemap(m, am->ARMam2.RI.reg);
311 //am->ARMam2.RR.base =lookupHRegRemap(m, am->ARMam2.RR.base);
312 //am->ARMam2.RR.index = lookupHRegRemap(m, am->ARMam2.RR.index);
315 vpanic("mapRegs_ARMAmode2");
320 /* --------- Mem AModes: Addressing Mode VFP --------- */
322 ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 ) {
323 ARMAModeV* am = LibVEX_Alloc(sizeof(ARMAModeV));
324 vassert(simm11 >= -1020 && simm11 <= 1020);
325 vassert(0 == (simm11 & 3));
331 void ppARMAModeV ( ARMAModeV* am ) {
332 vex_printf("%d(", am->simm11);
337 static void addRegUsage_ARMAModeV ( HRegUsage* u, ARMAModeV* am ) {
338 addHRegUse(u, HRmRead, am->reg);
341 static void mapRegs_ARMAModeV ( HRegRemap* m, ARMAModeV* am ) {
342 am->reg = lookupHRegRemap(m, am->reg);
346 /* --------- Reg or imm-8x4 operands --------- */
348 static UInt ROR32 ( UInt x, UInt sh ) {
349 vassert(sh >= 0 && sh < 32);
353 return (x << (32-sh)) | (x >> sh);
356 ARMRI84* ARMRI84_I84 ( UShort imm8, UShort imm4 ) {
357 ARMRI84* ri84 = LibVEX_Alloc(sizeof(ARMRI84));
358 ri84->tag = ARMri84_I84;
359 ri84->ARMri84.I84.imm8 = imm8;
360 ri84->ARMri84.I84.imm4 = imm4;
361 vassert(imm8 >= 0 && imm8 <= 255);
362 vassert(imm4 >= 0 && imm4 <= 15);
365 ARMRI84* ARMRI84_R ( HReg reg ) {
366 ARMRI84* ri84 = LibVEX_Alloc(sizeof(ARMRI84));
367 ri84->tag = ARMri84_R;
368 ri84->ARMri84.R.reg = reg;
372 void ppARMRI84 ( ARMRI84* ri84 ) {
375 vex_printf("0x%x", ROR32(ri84->ARMri84.I84.imm8,
376 2 * ri84->ARMri84.I84.imm4));
379 ppHRegARM(ri84->ARMri84.R.reg);
386 static void addRegUsage_ARMRI84 ( HRegUsage* u, ARMRI84* ri84 ) {
391 addHRegUse(u, HRmRead, ri84->ARMri84.R.reg);
394 vpanic("addRegUsage_ARMRI84");
398 static void mapRegs_ARMRI84 ( HRegRemap* m, ARMRI84* ri84 ) {
403 ri84->ARMri84.R.reg = lookupHRegRemap(m, ri84->ARMri84.R.reg);
406 vpanic("mapRegs_ARMRI84");
411 /* --------- Reg or imm5 operands --------- */
413 ARMRI5* ARMRI5_I5 ( UInt imm5 ) {
414 ARMRI5* ri5 = LibVEX_Alloc(sizeof(ARMRI5));
415 ri5->tag = ARMri5_I5;
416 ri5->ARMri5.I5.imm5 = imm5;
417 vassert(imm5 > 0 && imm5 <= 31); // zero is not allowed
420 ARMRI5* ARMRI5_R ( HReg reg ) {
421 ARMRI5* ri5 = LibVEX_Alloc(sizeof(ARMRI5));
423 ri5->ARMri5.R.reg = reg;
427 void ppARMRI5 ( ARMRI5* ri5 ) {
430 vex_printf("%u", ri5->ARMri5.I5.imm5);
433 ppHRegARM(ri5->ARMri5.R.reg);
440 static void addRegUsage_ARMRI5 ( HRegUsage* u, ARMRI5* ri5 ) {
445 addHRegUse(u, HRmRead, ri5->ARMri5.R.reg);
448 vpanic("addRegUsage_ARMRI5");
452 static void mapRegs_ARMRI5 ( HRegRemap* m, ARMRI5* ri5 ) {
457 ri5->ARMri5.R.reg = lookupHRegRemap(m, ri5->ARMri5.R.reg);
460 vpanic("mapRegs_ARMRI5");
465 /* --------- Instructions. --------- */
467 HChar* showARMAluOp ( ARMAluOp op ) {
469 case ARMalu_ADD: return "add";
470 case ARMalu_ADDS: return "adds";
471 case ARMalu_ADC: return "adc";
472 case ARMalu_SUB: return "sub";
473 case ARMalu_SUBS: return "subs";
474 case ARMalu_SBC: return "sbc";
475 case ARMalu_AND: return "and";
476 case ARMalu_BIC: return "bic";
477 case ARMalu_OR: return "orr";
478 case ARMalu_XOR: return "xor";
479 default: vpanic("showARMAluOp");
483 HChar* showARMShiftOp ( ARMShiftOp op ) {
485 case ARMsh_SHL: return "shl";
486 case ARMsh_SHR: return "shr";
487 case ARMsh_SAR: return "sar";
488 default: vpanic("showARMShiftOp");
492 HChar* showARMUnaryOp ( ARMUnaryOp op ) {
494 case ARMun_NEG: return "neg";
495 case ARMun_NOT: return "not";
496 case ARMun_CLZ: return "clz";
497 default: vpanic("showARMUnaryOp");
501 HChar* showARMMulOp ( ARMMulOp op ) {
503 case ARMmul_PLAIN: return "mul";
504 case ARMmul_ZX: return "umull";
505 case ARMmul_SX: return "smull";
506 default: vpanic("showARMMulOp");
510 HChar* showARMVfpOp ( ARMVfpOp op ) {
512 case ARMvfp_ADD: return "add";
513 case ARMvfp_SUB: return "sub";
514 case ARMvfp_MUL: return "mul";
515 case ARMvfp_DIV: return "div";
516 default: vpanic("showARMVfpOp");
520 HChar* showARMVfpUnaryOp ( ARMVfpUnaryOp op ) {
522 case ARMvfpu_COPY: return "cpy";
523 case ARMvfpu_NEG: return "neg";
524 case ARMvfpu_ABS: return "abs";
525 case ARMvfpu_SQRT: return "sqrt";
526 default: vpanic("showARMVfpUnaryOp");
530 ARMInstr* ARMInstr_Alu ( ARMAluOp op,
531 HReg dst, HReg argL, ARMRI84* argR ) {
532 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
534 i->ARMin.Alu.op = op;
535 i->ARMin.Alu.dst = dst;
536 i->ARMin.Alu.argL = argL;
537 i->ARMin.Alu.argR = argR;
540 ARMInstr* ARMInstr_Shift ( ARMShiftOp op,
541 HReg dst, HReg argL, ARMRI5* argR ) {
542 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
543 i->tag = ARMin_Shift;
544 i->ARMin.Shift.op = op;
545 i->ARMin.Shift.dst = dst;
546 i->ARMin.Shift.argL = argL;
547 i->ARMin.Shift.argR = argR;
550 ARMInstr* ARMInstr_Unary ( ARMUnaryOp op, HReg dst, HReg src ) {
551 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
552 i->tag = ARMin_Unary;
553 i->ARMin.Unary.op = op;
554 i->ARMin.Unary.dst = dst;
555 i->ARMin.Unary.src = src;
558 ARMInstr* ARMInstr_CmpOrTst ( Bool isCmp, HReg argL, ARMRI84* argR ) {
559 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
560 i->tag = ARMin_CmpOrTst;
561 i->ARMin.CmpOrTst.isCmp = isCmp;
562 i->ARMin.CmpOrTst.argL = argL;
563 i->ARMin.CmpOrTst.argR = argR;
566 ARMInstr* ARMInstr_Mov ( HReg dst, ARMRI84* src ) {
567 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
569 i->ARMin.Mov.dst = dst;
570 i->ARMin.Mov.src = src;
573 ARMInstr* ARMInstr_Imm32 ( HReg dst, UInt imm32 ) {
574 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
575 i->tag = ARMin_Imm32;
576 i->ARMin.Imm32.dst = dst;
577 i->ARMin.Imm32.imm32 = imm32;
580 ARMInstr* ARMInstr_LdSt32 ( Bool isLoad, HReg rD, ARMAMode1* amode ) {
581 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
582 i->tag = ARMin_LdSt32;
583 i->ARMin.LdSt32.isLoad = isLoad;
584 i->ARMin.LdSt32.rD = rD;
585 i->ARMin.LdSt32.amode = amode;
588 ARMInstr* ARMInstr_LdSt16 ( Bool isLoad, Bool signedLoad,
589 HReg rD, ARMAMode2* amode ) {
590 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
591 i->tag = ARMin_LdSt16;
592 i->ARMin.LdSt16.isLoad = isLoad;
593 i->ARMin.LdSt16.signedLoad = signedLoad;
594 i->ARMin.LdSt16.rD = rD;
595 i->ARMin.LdSt16.amode = amode;
598 ARMInstr* ARMInstr_LdSt8U ( Bool isLoad, HReg rD, ARMAMode1* amode ) {
599 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
600 i->tag = ARMin_LdSt8U;
601 i->ARMin.LdSt8U.isLoad = isLoad;
602 i->ARMin.LdSt8U.rD = rD;
603 i->ARMin.LdSt8U.amode = amode;
606 //extern ARMInstr* ARMInstr_Ld8S ( HReg, ARMAMode2* );
607 ARMInstr* ARMInstr_Goto ( IRJumpKind jk, ARMCondCode cond, HReg gnext ) {
608 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
610 i->ARMin.Goto.jk = jk;
611 i->ARMin.Goto.cond = cond;
612 i->ARMin.Goto.gnext = gnext;
615 ARMInstr* ARMInstr_CMov ( ARMCondCode cond, HReg dst, ARMRI84* src ) {
616 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
618 i->ARMin.CMov.cond = cond;
619 i->ARMin.CMov.dst = dst;
620 i->ARMin.CMov.src = src;
621 vassert(cond != ARMcc_AL);
624 ARMInstr* ARMInstr_Call ( ARMCondCode cond, HWord target, Int nArgRegs ) {
625 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
627 i->ARMin.Call.cond = cond;
628 i->ARMin.Call.target = target;
629 i->ARMin.Call.nArgRegs = nArgRegs;
632 ARMInstr* ARMInstr_Mul ( ARMMulOp op ) {
633 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
635 i->ARMin.Mul.op = op;
638 ARMInstr* ARMInstr_LdrEX ( Int szB ) {
639 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
640 i->tag = ARMin_LdrEX;
641 i->ARMin.LdrEX.szB = szB;
642 vassert(szB == 4 || szB == 1);
645 ARMInstr* ARMInstr_StrEX ( Int szB ) {
646 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
647 i->tag = ARMin_StrEX;
648 i->ARMin.StrEX.szB = szB;
649 vassert(szB == 4 || szB == 1);
652 ARMInstr* ARMInstr_VLdStD ( Bool isLoad, HReg dD, ARMAModeV* am ) {
653 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
654 i->tag = ARMin_VLdStD;
655 i->ARMin.VLdStD.isLoad = isLoad;
656 i->ARMin.VLdStD.dD = dD;
657 i->ARMin.VLdStD.amode = am;
660 ARMInstr* ARMInstr_VLdStS ( Bool isLoad, HReg fD, ARMAModeV* am ) {
661 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
662 i->tag = ARMin_VLdStS;
663 i->ARMin.VLdStS.isLoad = isLoad;
664 i->ARMin.VLdStS.fD = fD;
665 i->ARMin.VLdStS.amode = am;
668 ARMInstr* ARMInstr_VAluD ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
669 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
670 i->tag = ARMin_VAluD;
671 i->ARMin.VAluD.op = op;
672 i->ARMin.VAluD.dst = dst;
673 i->ARMin.VAluD.argL = argL;
674 i->ARMin.VAluD.argR = argR;
677 ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
678 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
679 i->tag = ARMin_VAluS;
680 i->ARMin.VAluS.op = op;
681 i->ARMin.VAluS.dst = dst;
682 i->ARMin.VAluS.argL = argL;
683 i->ARMin.VAluS.argR = argR;
686 ARMInstr* ARMInstr_VUnaryD ( ARMVfpUnaryOp op, HReg dst, HReg src ) {
687 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
688 i->tag = ARMin_VUnaryD;
689 i->ARMin.VUnaryD.op = op;
690 i->ARMin.VUnaryD.dst = dst;
691 i->ARMin.VUnaryD.src = src;
694 ARMInstr* ARMInstr_VUnaryS ( ARMVfpUnaryOp op, HReg dst, HReg src ) {
695 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
696 i->tag = ARMin_VUnaryS;
697 i->ARMin.VUnaryS.op = op;
698 i->ARMin.VUnaryS.dst = dst;
699 i->ARMin.VUnaryS.src = src;
702 ARMInstr* ARMInstr_VCmpD ( HReg argL, HReg argR ) {
703 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
704 i->tag = ARMin_VCmpD;
705 i->ARMin.VCmpD.argL = argL;
706 i->ARMin.VCmpD.argR = argR;
709 ARMInstr* ARMInstr_VCMovD ( ARMCondCode cond, HReg dst, HReg src ) {
710 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
711 i->tag = ARMin_VCMovD;
712 i->ARMin.VCMovD.cond = cond;
713 i->ARMin.VCMovD.dst = dst;
714 i->ARMin.VCMovD.src = src;
715 vassert(cond != ARMcc_AL);
718 ARMInstr* ARMInstr_VCMovS ( ARMCondCode cond, HReg dst, HReg src ) {
719 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
720 i->tag = ARMin_VCMovS;
721 i->ARMin.VCMovS.cond = cond;
722 i->ARMin.VCMovS.dst = dst;
723 i->ARMin.VCMovS.src = src;
724 vassert(cond != ARMcc_AL);
727 ARMInstr* ARMInstr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
728 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
729 i->tag = ARMin_VCvtSD;
730 i->ARMin.VCvtSD.sToD = sToD;
731 i->ARMin.VCvtSD.dst = dst;
732 i->ARMin.VCvtSD.src = src;
735 ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo ) {
736 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
737 i->tag = ARMin_VXferD;
738 i->ARMin.VXferD.toD = toD;
739 i->ARMin.VXferD.dD = dD;
740 i->ARMin.VXferD.rHi = rHi;
741 i->ARMin.VXferD.rLo = rLo;
744 ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo ) {
745 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
746 i->tag = ARMin_VXferS;
747 i->ARMin.VXferS.toS = toS;
748 i->ARMin.VXferS.fD = fD;
749 i->ARMin.VXferS.rLo = rLo;
752 ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned,
753 HReg dst, HReg src ) {
754 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
755 i->tag = ARMin_VCvtID;
756 i->ARMin.VCvtID.iToD = iToD;
757 i->ARMin.VCvtID.syned = syned;
758 i->ARMin.VCvtID.dst = dst;
759 i->ARMin.VCvtID.src = src;
762 ARMInstr* ARMInstr_FPSCR ( Bool toFPSCR, HReg iReg ) {
763 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
764 i->tag = ARMin_FPSCR;
765 i->ARMin.FPSCR.toFPSCR = toFPSCR;
766 i->ARMin.FPSCR.iReg = iReg;
769 ARMInstr* ARMInstr_MFence ( void ) {
770 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
771 i->tag = ARMin_MFence;
775 void ppARMInstr ( ARMInstr* i ) {
778 vex_printf("%-4s ", showARMAluOp(i->ARMin.Alu.op));
779 ppHRegARM(i->ARMin.Alu.dst);
781 ppHRegARM(i->ARMin.Alu.argL);
783 ppARMRI84(i->ARMin.Alu.argR);
786 vex_printf("%s ", showARMShiftOp(i->ARMin.Shift.op));
787 ppHRegARM(i->ARMin.Shift.dst);
789 ppHRegARM(i->ARMin.Shift.argL);
791 ppARMRI5(i->ARMin.Shift.argR);
794 vex_printf("%s ", showARMUnaryOp(i->ARMin.Unary.op));
795 ppHRegARM(i->ARMin.Unary.dst);
797 ppHRegARM(i->ARMin.Unary.src);
800 vex_printf("%s ", i->ARMin.CmpOrTst.isCmp ? "cmp" : "tst");
801 ppHRegARM(i->ARMin.CmpOrTst.argL);
803 ppARMRI84(i->ARMin.CmpOrTst.argR);
807 ppHRegARM(i->ARMin.Mov.dst);
809 ppARMRI84(i->ARMin.Mov.src);
813 ppHRegARM(i->ARMin.Imm32.dst);
814 vex_printf(", 0x%x", i->ARMin.Imm32.imm32);
817 if (i->ARMin.LdSt32.isLoad) {
819 ppHRegARM(i->ARMin.LdSt32.rD);
821 ppARMAMode1(i->ARMin.LdSt32.amode);
824 ppARMAMode1(i->ARMin.LdSt32.amode);
826 ppHRegARM(i->ARMin.LdSt32.rD);
830 if (i->ARMin.LdSt16.isLoad) {
831 vex_printf("%s", i->ARMin.LdSt16.signedLoad
832 ? "ldrsh " : "ldrh " );
833 ppHRegARM(i->ARMin.LdSt16.rD);
835 ppARMAMode2(i->ARMin.LdSt16.amode);
838 ppARMAMode2(i->ARMin.LdSt16.amode);
840 ppHRegARM(i->ARMin.LdSt16.rD);
844 if (i->ARMin.LdSt8U.isLoad) {
846 ppHRegARM(i->ARMin.LdSt8U.rD);
848 ppARMAMode1(i->ARMin.LdSt8U.amode);
851 ppARMAMode1(i->ARMin.LdSt8U.amode);
853 ppHRegARM(i->ARMin.LdSt8U.rD);
859 if (i->ARMin.Goto.cond != ARMcc_AL) {
860 vex_printf("if (%%cpsr.%s) { ",
861 showARMCondCode(i->ARMin.Goto.cond));
863 vex_printf("if (1) { ");
865 if (i->ARMin.Goto.jk != Ijk_Boring
866 && i->ARMin.Goto.jk != Ijk_Call
867 && i->ARMin.Goto.jk != Ijk_Ret) {
868 vex_printf("mov r8, $");
869 ppIRJumpKind(i->ARMin.Goto.jk);
872 vex_printf("mov r0, ");
873 ppHRegARM(i->ARMin.Goto.gnext);
874 vex_printf(" ; bx r14");
875 if (i->ARMin.Goto.cond != ARMcc_AL) {
882 vex_printf("mov%s ", showARMCondCode(i->ARMin.CMov.cond));
883 ppHRegARM(i->ARMin.CMov.dst);
885 ppARMRI84(i->ARMin.CMov.src);
888 vex_printf("call%s ",
889 i->ARMin.Call.cond==ARMcc_AL
890 ? "" : showARMCondCode(i->ARMin.Call.cond));
891 vex_printf("0x%lx [nArgRegs=%d]",
892 i->ARMin.Call.target, i->ARMin.Call.nArgRegs);
895 vex_printf("%-5s ", showARMMulOp(i->ARMin.Mul.op));
896 if (i->ARMin.Mul.op == ARMmul_PLAIN) {
897 vex_printf("r0, r2, r3");
899 vex_printf("r1:r0, r2, r3");
903 vex_printf("ldrex%s ", i->ARMin.LdrEX.szB == 1 ? "b"
904 : i->ARMin.LdrEX.szB == 2 ? "h" : "");
905 vex_printf("r0, [r1]");
908 vex_printf("strex%s ", i->ARMin.StrEX.szB == 1 ? "b"
909 : i->ARMin.StrEX.szB == 2 ? "h" : "");
910 vex_printf("r0, r1, [r2]");
913 if (i->ARMin.VLdStD.isLoad) {
915 ppHRegARM(i->ARMin.VLdStD.dD);
917 ppARMAModeV(i->ARMin.VLdStD.amode);
920 ppARMAModeV(i->ARMin.VLdStD.amode);
922 ppHRegARM(i->ARMin.VLdStD.dD);
926 if (i->ARMin.VLdStS.isLoad) {
928 ppHRegARM(i->ARMin.VLdStS.fD);
930 ppARMAModeV(i->ARMin.VLdStS.amode);
933 ppARMAModeV(i->ARMin.VLdStS.amode);
935 ppHRegARM(i->ARMin.VLdStS.fD);
939 vex_printf("f%-3sd ", showARMVfpOp(i->ARMin.VAluD.op));
940 ppHRegARM(i->ARMin.VAluD.dst);
942 ppHRegARM(i->ARMin.VAluD.argL);
944 ppHRegARM(i->ARMin.VAluD.argR);
947 vex_printf("f%-3ss ", showARMVfpOp(i->ARMin.VAluS.op));
948 ppHRegARM(i->ARMin.VAluS.dst);
950 ppHRegARM(i->ARMin.VAluS.argL);
952 ppHRegARM(i->ARMin.VAluS.argR);
955 vex_printf("f%-3sd ", showARMVfpUnaryOp(i->ARMin.VUnaryD.op));
956 ppHRegARM(i->ARMin.VUnaryD.dst);
958 ppHRegARM(i->ARMin.VUnaryD.src);
961 vex_printf("f%-3ss ", showARMVfpUnaryOp(i->ARMin.VUnaryS.op));
962 ppHRegARM(i->ARMin.VUnaryS.dst);
964 ppHRegARM(i->ARMin.VUnaryS.src);
967 vex_printf("fcmpd ");
968 ppHRegARM(i->ARMin.VCmpD.argL);
970 ppHRegARM(i->ARMin.VCmpD.argR);
971 vex_printf(" ; fmstat");
974 vex_printf("fcpyd%s ", showARMCondCode(i->ARMin.VCMovD.cond));
975 ppHRegARM(i->ARMin.VCMovD.dst);
977 ppHRegARM(i->ARMin.VCMovD.src);
980 vex_printf("fcpys%s ", showARMCondCode(i->ARMin.VCMovS.cond));
981 ppHRegARM(i->ARMin.VCMovS.dst);
983 ppHRegARM(i->ARMin.VCMovS.src);
986 vex_printf("fcvt%s ", i->ARMin.VCvtSD.sToD ? "ds" : "sd");
987 ppHRegARM(i->ARMin.VCvtSD.dst);
989 ppHRegARM(i->ARMin.VCvtSD.src);
993 if (i->ARMin.VXferD.toD) {
994 ppHRegARM(i->ARMin.VXferD.dD);
996 ppHRegARM(i->ARMin.VXferD.rLo);
998 ppHRegARM(i->ARMin.VXferD.rHi);
1000 ppHRegARM(i->ARMin.VXferD.rLo);
1002 ppHRegARM(i->ARMin.VXferD.rHi);
1004 ppHRegARM(i->ARMin.VXferD.dD);
1008 vex_printf("vmov ");
1009 if (i->ARMin.VXferS.toS) {
1010 ppHRegARM(i->ARMin.VXferS.fD);
1012 ppHRegARM(i->ARMin.VXferS.rLo);
1014 ppHRegARM(i->ARMin.VXferS.rLo);
1016 ppHRegARM(i->ARMin.VXferS.fD);
1019 case ARMin_VCvtID: {
1021 if (i->ARMin.VCvtID.iToD) {
1022 nm = i->ARMin.VCvtID.syned ? "fsitod" : "fuitod";
1024 nm = i->ARMin.VCvtID.syned ? "ftosid" : "ftouid";
1026 vex_printf("%s ", nm);
1027 ppHRegARM(i->ARMin.VCvtID.dst);
1029 ppHRegARM(i->ARMin.VCvtID.src);
1033 if (i->ARMin.FPSCR.toFPSCR) {
1034 vex_printf("fmxr fpscr, ");
1035 ppHRegARM(i->ARMin.FPSCR.iReg);
1037 vex_printf("fmrx ");
1038 ppHRegARM(i->ARMin.FPSCR.iReg);
1039 vex_printf(", fpscr");
1043 vex_printf("mfence (mcr 15,0,r0,c7,c10,4; 15,0,r0,c7,c10,5; "
1044 "15,0,r0,c7,c5,4)");
1048 vex_printf("ppARMInstr: unhandled case (tag %d)", (Int)i->tag);
1049 vpanic("ppARMInstr(1)");
1052 vpanic("ppARMInstr(2)");
1057 /* --------- Helpers for register allocation. --------- */
1059 void getRegUsage_ARMInstr ( HRegUsage* u, ARMInstr* i, Bool mode64 )
1061 vassert(mode64 == False);
1065 addHRegUse(u, HRmWrite, i->ARMin.Alu.dst);
1066 addHRegUse(u, HRmRead, i->ARMin.Alu.argL);
1067 addRegUsage_ARMRI84(u, i->ARMin.Alu.argR);
1070 addHRegUse(u, HRmWrite, i->ARMin.Shift.dst);
1071 addHRegUse(u, HRmRead, i->ARMin.Shift.argL);
1072 addRegUsage_ARMRI5(u, i->ARMin.Shift.argR);
1075 addHRegUse(u, HRmWrite, i->ARMin.Unary.dst);
1076 addHRegUse(u, HRmRead, i->ARMin.Unary.src);
1078 case ARMin_CmpOrTst:
1079 addHRegUse(u, HRmRead, i->ARMin.CmpOrTst.argL);
1080 addRegUsage_ARMRI84(u, i->ARMin.CmpOrTst.argR);
1083 addHRegUse(u, HRmWrite, i->ARMin.Mov.dst);
1084 addRegUsage_ARMRI84(u, i->ARMin.Mov.src);
1087 addHRegUse(u, HRmWrite, i->ARMin.Imm32.dst);
1090 addRegUsage_ARMAMode1(u, i->ARMin.LdSt32.amode);
1091 if (i->ARMin.LdSt32.isLoad) {
1092 addHRegUse(u, HRmWrite, i->ARMin.LdSt32.rD);
1094 addHRegUse(u, HRmRead, i->ARMin.LdSt32.rD);
1098 addRegUsage_ARMAMode2(u, i->ARMin.LdSt16.amode);
1099 if (i->ARMin.LdSt16.isLoad) {
1100 addHRegUse(u, HRmWrite, i->ARMin.LdSt16.rD);
1102 addHRegUse(u, HRmRead, i->ARMin.LdSt16.rD);
1106 addRegUsage_ARMAMode1(u, i->ARMin.LdSt8U.amode);
1107 if (i->ARMin.LdSt8U.isLoad) {
1108 addHRegUse(u, HRmWrite, i->ARMin.LdSt8U.rD);
1110 addHRegUse(u, HRmRead, i->ARMin.LdSt8U.rD);
1116 /* reads the reg holding the next guest addr */
1117 addHRegUse(u, HRmRead, i->ARMin.Goto.gnext);
1118 /* writes it to the standard integer return register */
1119 addHRegUse(u, HRmWrite, hregARM_R0());
1120 /* possibly messes with the baseblock pointer */
1121 if (i->ARMin.Goto.jk != Ijk_Boring
1122 && i->ARMin.Goto.jk != Ijk_Call
1123 && i->ARMin.Goto.jk != Ijk_Ret)
1124 /* note, this is irrelevant since r8 is not actually
1125 available to the allocator. But still .. */
1126 addHRegUse(u, HRmWrite, hregARM_R8());
1129 addHRegUse(u, HRmWrite, i->ARMin.CMov.dst);
1130 addHRegUse(u, HRmRead, i->ARMin.CMov.dst);
1131 addRegUsage_ARMRI84(u, i->ARMin.CMov.src);
1134 /* logic and comments copied/modified from x86 back end */
1135 /* This is a bit subtle. */
1136 /* First off, claim it trashes all the caller-saved regs
1137 which fall within the register allocator's jurisdiction.
1138 These I believe to be r0,1,2,3. If it turns out that r9
1139 is also caller-saved, then we'll have to add that here
1141 addHRegUse(u, HRmWrite, hregARM_R0());
1142 addHRegUse(u, HRmWrite, hregARM_R1());
1143 addHRegUse(u, HRmWrite, hregARM_R2());
1144 addHRegUse(u, HRmWrite, hregARM_R3());
1145 /* Now we have to state any parameter-carrying registers
1146 which might be read. This depends on nArgRegs. */
1147 switch (i->ARMin.Call.nArgRegs) {
1148 case 4: addHRegUse(u, HRmRead, hregARM_R3()); /*fallthru*/
1149 case 3: addHRegUse(u, HRmRead, hregARM_R2()); /*fallthru*/
1150 case 2: addHRegUse(u, HRmRead, hregARM_R1()); /*fallthru*/
1151 case 1: addHRegUse(u, HRmRead, hregARM_R0()); break;
1153 default: vpanic("getRegUsage_ARM:Call:regparms");
1155 /* Finally, there is the issue that the insn trashes a
1156 register because the literal target address has to be
1157 loaded into a register. Fortunately, for the nArgRegs=
1158 0/1/2/3 case, we can use r0, r1, r2 or r3 respectively, so
1159 this does not cause any further damage. For the
1160 nArgRegs=4 case, we'll have to choose another register
1161 arbitrarily since all the caller saved regs are used for
1162 parameters, and so we might as well choose r11.
1164 if (i->ARMin.Call.nArgRegs == 4)
1165 addHRegUse(u, HRmWrite, hregARM_R11());
1166 /* Upshot of this is that the assembler really must observe
1167 the here-stated convention of which register to use as an
1168 address temporary, depending on nArgRegs: 0==r0,
1169 1==r1, 2==r2, 3==r3, 4==r11 */
1172 addHRegUse(u, HRmRead, hregARM_R2());
1173 addHRegUse(u, HRmRead, hregARM_R3());
1174 addHRegUse(u, HRmWrite, hregARM_R0());
1175 if (i->ARMin.Mul.op != ARMmul_PLAIN)
1176 addHRegUse(u, HRmWrite, hregARM_R1());
1179 addHRegUse(u, HRmWrite, hregARM_R0());
1180 addHRegUse(u, HRmRead, hregARM_R1());
1183 addHRegUse(u, HRmWrite, hregARM_R0());
1184 addHRegUse(u, HRmRead, hregARM_R1());
1185 addHRegUse(u, HRmRead, hregARM_R2());
1188 addRegUsage_ARMAModeV(u, i->ARMin.VLdStD.amode);
1189 if (i->ARMin.VLdStD.isLoad) {
1190 addHRegUse(u, HRmWrite, i->ARMin.VLdStD.dD);
1192 addHRegUse(u, HRmRead, i->ARMin.VLdStD.dD);
1196 addRegUsage_ARMAModeV(u, i->ARMin.VLdStS.amode);
1197 if (i->ARMin.VLdStS.isLoad) {
1198 addHRegUse(u, HRmWrite, i->ARMin.VLdStS.fD);
1200 addHRegUse(u, HRmRead, i->ARMin.VLdStS.fD);
1204 addHRegUse(u, HRmWrite, i->ARMin.VAluD.dst);
1205 addHRegUse(u, HRmRead, i->ARMin.VAluD.argL);
1206 addHRegUse(u, HRmRead, i->ARMin.VAluD.argR);
1209 addHRegUse(u, HRmWrite, i->ARMin.VAluS.dst);
1210 addHRegUse(u, HRmRead, i->ARMin.VAluS.argL);
1211 addHRegUse(u, HRmRead, i->ARMin.VAluS.argR);
1214 addHRegUse(u, HRmWrite, i->ARMin.VUnaryD.dst);
1215 addHRegUse(u, HRmRead, i->ARMin.VUnaryD.src);
1218 addHRegUse(u, HRmWrite, i->ARMin.VUnaryS.dst);
1219 addHRegUse(u, HRmRead, i->ARMin.VUnaryS.src);
1222 addHRegUse(u, HRmRead, i->ARMin.VCmpD.argL);
1223 addHRegUse(u, HRmRead, i->ARMin.VCmpD.argR);
1226 addHRegUse(u, HRmWrite, i->ARMin.VCMovD.dst);
1227 addHRegUse(u, HRmRead, i->ARMin.VCMovD.dst);
1228 addHRegUse(u, HRmRead, i->ARMin.VCMovD.src);
1231 addHRegUse(u, HRmWrite, i->ARMin.VCMovS.dst);
1232 addHRegUse(u, HRmRead, i->ARMin.VCMovS.dst);
1233 addHRegUse(u, HRmRead, i->ARMin.VCMovS.src);
1236 addHRegUse(u, HRmWrite, i->ARMin.VCvtSD.dst);
1237 addHRegUse(u, HRmRead, i->ARMin.VCvtSD.src);
1240 if (i->ARMin.VXferD.toD) {
1241 addHRegUse(u, HRmWrite, i->ARMin.VXferD.dD);
1242 addHRegUse(u, HRmRead, i->ARMin.VXferD.rHi);
1243 addHRegUse(u, HRmRead, i->ARMin.VXferD.rLo);
1245 addHRegUse(u, HRmRead, i->ARMin.VXferD.dD);
1246 addHRegUse(u, HRmWrite, i->ARMin.VXferD.rHi);
1247 addHRegUse(u, HRmWrite, i->ARMin.VXferD.rLo);
1251 if (i->ARMin.VXferS.toS) {
1252 addHRegUse(u, HRmWrite, i->ARMin.VXferS.fD);
1253 addHRegUse(u, HRmRead, i->ARMin.VXferS.rLo);
1255 addHRegUse(u, HRmRead, i->ARMin.VXferS.fD);
1256 addHRegUse(u, HRmWrite, i->ARMin.VXferS.rLo);
1260 addHRegUse(u, HRmWrite, i->ARMin.VCvtID.dst);
1261 addHRegUse(u, HRmRead, i->ARMin.VCvtID.src);
1264 if (i->ARMin.FPSCR.toFPSCR)
1265 addHRegUse(u, HRmRead, i->ARMin.FPSCR.iReg);
1267 addHRegUse(u, HRmWrite, i->ARMin.FPSCR.iReg);
1274 vpanic("getRegUsage_ARMInstr");
1279 void mapRegs_ARMInstr ( HRegRemap* m, ARMInstr* i, Bool mode64 )
1281 vassert(mode64 == False);
1284 i->ARMin.Alu.dst = lookupHRegRemap(m, i->ARMin.Alu.dst);
1285 i->ARMin.Alu.argL = lookupHRegRemap(m, i->ARMin.Alu.argL);
1286 mapRegs_ARMRI84(m, i->ARMin.Alu.argR);
1289 i->ARMin.Shift.dst = lookupHRegRemap(m, i->ARMin.Shift.dst);
1290 i->ARMin.Shift.argL = lookupHRegRemap(m, i->ARMin.Shift.argL);
1291 mapRegs_ARMRI5(m, i->ARMin.Shift.argR);
1294 i->ARMin.Unary.dst = lookupHRegRemap(m, i->ARMin.Unary.dst);
1295 i->ARMin.Unary.src = lookupHRegRemap(m, i->ARMin.Unary.src);
1297 case ARMin_CmpOrTst:
1298 i->ARMin.CmpOrTst.argL = lookupHRegRemap(m, i->ARMin.CmpOrTst.argL);
1299 mapRegs_ARMRI84(m, i->ARMin.CmpOrTst.argR);
1302 i->ARMin.Mov.dst = lookupHRegRemap(m, i->ARMin.Mov.dst);
1303 mapRegs_ARMRI84(m, i->ARMin.Mov.src);
1306 i->ARMin.Imm32.dst = lookupHRegRemap(m, i->ARMin.Imm32.dst);
1309 i->ARMin.LdSt32.rD = lookupHRegRemap(m, i->ARMin.LdSt32.rD);
1310 mapRegs_ARMAMode1(m, i->ARMin.LdSt32.amode);
1313 i->ARMin.LdSt16.rD = lookupHRegRemap(m, i->ARMin.LdSt16.rD);
1314 mapRegs_ARMAMode2(m, i->ARMin.LdSt16.amode);
1317 i->ARMin.LdSt8U.rD = lookupHRegRemap(m, i->ARMin.LdSt8U.rD);
1318 mapRegs_ARMAMode1(m, i->ARMin.LdSt8U.amode);
1323 i->ARMin.Goto.gnext = lookupHRegRemap(m, i->ARMin.Goto.gnext);
1326 i->ARMin.CMov.dst = lookupHRegRemap(m, i->ARMin.CMov.dst);
1327 mapRegs_ARMRI84(m, i->ARMin.CMov.src);
1338 i->ARMin.VLdStD.dD = lookupHRegRemap(m, i->ARMin.VLdStD.dD);
1339 mapRegs_ARMAModeV(m, i->ARMin.VLdStD.amode);
1342 i->ARMin.VLdStS.fD = lookupHRegRemap(m, i->ARMin.VLdStS.fD);
1343 mapRegs_ARMAModeV(m, i->ARMin.VLdStS.amode);
1346 i->ARMin.VAluD.dst = lookupHRegRemap(m, i->ARMin.VAluD.dst);
1347 i->ARMin.VAluD.argL = lookupHRegRemap(m, i->ARMin.VAluD.argL);
1348 i->ARMin.VAluD.argR = lookupHRegRemap(m, i->ARMin.VAluD.argR);
1351 i->ARMin.VAluS.dst = lookupHRegRemap(m, i->ARMin.VAluS.dst);
1352 i->ARMin.VAluS.argL = lookupHRegRemap(m, i->ARMin.VAluS.argL);
1353 i->ARMin.VAluS.argR = lookupHRegRemap(m, i->ARMin.VAluS.argR);
1356 i->ARMin.VUnaryD.dst = lookupHRegRemap(m, i->ARMin.VUnaryD.dst);
1357 i->ARMin.VUnaryD.src = lookupHRegRemap(m, i->ARMin.VUnaryD.src);
1360 i->ARMin.VUnaryS.dst = lookupHRegRemap(m, i->ARMin.VUnaryS.dst);
1361 i->ARMin.VUnaryS.src = lookupHRegRemap(m, i->ARMin.VUnaryS.src);
1364 i->ARMin.VCmpD.argL = lookupHRegRemap(m, i->ARMin.VCmpD.argL);
1365 i->ARMin.VCmpD.argR = lookupHRegRemap(m, i->ARMin.VCmpD.argR);
1368 i->ARMin.VCMovD.dst = lookupHRegRemap(m, i->ARMin.VCMovD.dst);
1369 i->ARMin.VCMovD.src = lookupHRegRemap(m, i->ARMin.VCMovD.src);
1372 i->ARMin.VCMovS.dst = lookupHRegRemap(m, i->ARMin.VCMovS.dst);
1373 i->ARMin.VCMovS.src = lookupHRegRemap(m, i->ARMin.VCMovS.src);
1376 i->ARMin.VCvtSD.dst = lookupHRegRemap(m, i->ARMin.VCvtSD.dst);
1377 i->ARMin.VCvtSD.src = lookupHRegRemap(m, i->ARMin.VCvtSD.src);
1380 i->ARMin.VXferD.dD = lookupHRegRemap(m, i->ARMin.VXferD.dD);
1381 i->ARMin.VXferD.rHi = lookupHRegRemap(m, i->ARMin.VXferD.rHi);
1382 i->ARMin.VXferD.rLo = lookupHRegRemap(m, i->ARMin.VXferD.rLo);
1385 i->ARMin.VXferS.fD = lookupHRegRemap(m, i->ARMin.VXferS.fD);
1386 i->ARMin.VXferS.rLo = lookupHRegRemap(m, i->ARMin.VXferS.rLo);
1389 i->ARMin.VCvtID.dst = lookupHRegRemap(m, i->ARMin.VCvtID.dst);
1390 i->ARMin.VCvtID.src = lookupHRegRemap(m, i->ARMin.VCvtID.src);
1393 i->ARMin.FPSCR.iReg = lookupHRegRemap(m, i->ARMin.FPSCR.iReg);
1400 vpanic("mapRegs_ARMInstr");
1404 /* Figure out if i represents a reg-reg move, and if so assign the
1405 source and destination to *src and *dst. If in doubt say No. Used
1406 by the register allocator to do move coalescing.
1408 Bool isMove_ARMInstr ( ARMInstr* i, HReg* src, HReg* dst )
1410 /* Moves between integer regs */
1413 if (i->ARMin.Mov.src->tag == ARMri84_R) {
1414 *src = i->ARMin.Mov.src->ARMri84.R.reg;
1415 *dst = i->ARMin.Mov.dst;
1420 if (i->ARMin.VUnaryD.op == ARMvfpu_COPY) {
1421 *src = i->ARMin.VUnaryD.src;
1422 *dst = i->ARMin.VUnaryD.dst;
1427 if (i->ARMin.VUnaryS.op == ARMvfpu_COPY) {
1428 *src = i->ARMin.VUnaryS.src;
1429 *dst = i->ARMin.VUnaryS.dst;
1437 // todo: float, vector moves
1442 /* Generate arm spill/reload instructions under the direction of the
1443 register allocator. Note it's critical these don't write the
1446 void genSpill_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1447 HReg rreg, Int offsetB, Bool mode64 )
1450 vassert(offsetB >= 0);
1451 vassert(!hregIsVirtual(rreg));
1452 vassert(mode64 == False);
1454 rclass = hregClass(rreg);
1457 vassert(offsetB <= 4095);
1458 *i1 = ARMInstr_LdSt32( False/*!isLoad*/,
1460 ARMAMode1_RI(hregARM_R8(), offsetB) );
1464 HReg r8 = hregARM_R8(); /* baseblock */
1465 HReg r12 = hregARM_R12(); /* spill temp */
1467 vassert(0 == (offsetB & 3));
1468 if (offsetB >= 1024) {
1469 *i1 = ARMInstr_Alu(ARMalu_ADD, r12, r8,
1470 ARMRI84_I84(1,11)); /* 1024 */
1474 vassert(offsetB <= 1020);
1475 if (rclass == HRcFlt32) {
1476 *i2 = ARMInstr_VLdStS( False/*!isLoad*/,
1478 mkARMAModeV(base, offsetB) );
1480 *i2 = ARMInstr_VLdStD( False/*!isLoad*/,
1482 mkARMAModeV(base, offsetB) );
1487 ppHRegClass(rclass);
1488 vpanic("genSpill_ARM: unimplemented regclass");
1492 void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1493 HReg rreg, Int offsetB, Bool mode64 )
1496 vassert(offsetB >= 0);
1497 vassert(!hregIsVirtual(rreg));
1498 vassert(mode64 == False);
1500 rclass = hregClass(rreg);
1503 vassert(offsetB <= 4095);
1504 *i1 = ARMInstr_LdSt32( True/*isLoad*/,
1506 ARMAMode1_RI(hregARM_R8(), offsetB) );
1510 HReg r8 = hregARM_R8(); /* baseblock */
1511 HReg r12 = hregARM_R12(); /* spill temp */
1513 vassert(0 == (offsetB & 3));
1514 if (offsetB >= 1024) {
1515 *i1 = ARMInstr_Alu(ARMalu_ADD, r12, r8,
1516 ARMRI84_I84(1,11)); /* 1024 */
1520 vassert(offsetB <= 1020);
1521 if (rclass == HRcFlt32) {
1522 *i2 = ARMInstr_VLdStS( True/*isLoad*/,
1524 mkARMAModeV(base, offsetB) );
1526 *i2 = ARMInstr_VLdStD( True/*isLoad*/,
1528 mkARMAModeV(base, offsetB) );
1533 ppHRegClass(rclass);
1534 vpanic("genReload_ARM: unimplemented regclass");
1539 /* Emit an instruction into buf and return the number of bytes used.
1540 Note that buf is not the insn's final place, and therefore it is
1541 imperative to emit position-independent code. */
1543 static inline UChar iregNo ( HReg r )
1546 vassert(hregClass(r) == HRcInt32);
1547 vassert(!hregIsVirtual(r));
1553 static inline UChar dregNo ( HReg r )
1556 vassert(hregClass(r) == HRcFlt64);
1557 vassert(!hregIsVirtual(r));
1563 static inline UChar fregNo ( HReg r )
1566 vassert(hregClass(r) == HRcFlt32);
1567 vassert(!hregIsVirtual(r));
1573 #define BITS4(zzb3,zzb2,zzb1,zzb0) \
1574 (((zzb3) << 3) | ((zzb2) << 2) | ((zzb1) << 1) | (zzb0))
1575 #define X0000 BITS4(0,0,0,0)
1576 #define X0001 BITS4(0,0,0,1)
1577 #define X0010 BITS4(0,0,1,0)
1578 #define X0011 BITS4(0,0,1,1)
1579 #define X0100 BITS4(0,1,0,0)
1580 #define X0101 BITS4(0,1,0,1)
1581 #define X0110 BITS4(0,1,1,0)
1582 #define X0111 BITS4(0,1,1,1)
1583 #define X1000 BITS4(1,0,0,0)
1584 #define X1001 BITS4(1,0,0,1)
1585 #define X1010 BITS4(1,0,1,0)
1586 #define X1011 BITS4(1,0,1,1)
1587 #define X1100 BITS4(1,1,0,0)
1588 #define X1101 BITS4(1,1,0,1)
1589 #define X1110 BITS4(1,1,1,0)
1590 #define X1111 BITS4(1,1,1,1)
1592 #define XXXXX___(zzx7,zzx6,zzx5,zzx4,zzx3) \
1593 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
1594 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
1595 (((zzx3) & 0xF) << 12))
1597 #define XXXXXX__(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2) \
1598 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
1599 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
1600 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8))
1602 #define XXXXX__X(zzx7,zzx6,zzx5,zzx4,zzx3,zzx0) \
1603 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
1604 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
1605 (((zzx3) & 0xF) << 12) | (((zzx0) & 0xF) << 0))
1607 #define XXX___XX(zzx7,zzx6,zzx5,zzx1,zzx0) \
1608 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
1609 (((zzx5) & 0xF) << 20) | (((zzx1) & 0xF) << 4) | \
1610 (((zzx0) & 0xF) << 0))
1612 #define XXXXXXXX(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2,zzx1,zzx0) \
1613 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
1614 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
1615 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8) | \
1616 (((zzx1) & 0xF) << 4) | (((zzx0) & 0xF) << 0))
1618 /* Generate a skeletal insn that involves an a RI84 shifter operand.
1619 Returns a word which is all zeroes apart from bits 25 and 11..0,
1620 since it is those that encode the shifter operand (at least to the
1621 extent that we care about it.) */
1622 static UInt skeletal_RI84 ( ARMRI84* ri )
1625 if (ri->tag == ARMri84_I84) {
1626 vassert(0 == (ri->ARMri84.I84.imm4 & ~0x0F));
1627 vassert(0 == (ri->ARMri84.I84.imm8 & ~0xFF));
1629 instr |= (ri->ARMri84.I84.imm4 << 8);
1630 instr |= ri->ARMri84.I84.imm8;
1633 instr |= iregNo(ri->ARMri84.R.reg);
1638 /* Ditto for RI5. Resulting word is zeroes apart from bit 4 and bits
1640 static UInt skeletal_RI5 ( ARMRI5* ri )
1643 if (ri->tag == ARMri5_I5) {
1644 UInt imm5 = ri->ARMri5.I5.imm5;
1645 vassert(imm5 >= 1 && imm5 <= 31);
1650 instr |= iregNo(ri->ARMri5.R.reg) << 8;
1656 /* Get an immediate into a register, using only that
1657 register. (very lame..) */
1658 static UInt* imm32_to_iregNo ( UInt* p, Int rD, UInt imm32 )
1661 vassert(rD >= 0 && rD <= 14); // r15 not good to mess with!
1663 if (0 == (imm32 & ~0xFF)) {
1664 /* mov with a immediate shifter operand of (0, imm32) (??) */
1665 instr = XXXXXX__(X1110,X0011,X1010,X0000,rD,X0000);
1669 // this is very bad; causes Dcache pollution
1671 instr = XXXXX___(X1110,X0101,X1001,X1111,rD);
1680 /* Generate movw rD, #low16. Then, if the high 16 are
1681 nonzero, generate movt rD, #high16. */
1682 UInt lo16 = imm32 & 0xFFFF;
1683 UInt hi16 = (imm32 >> 16) & 0xFFFF;
1684 instr = XXXXXXXX(0xE, 0x3, 0x0, (lo16 >> 12) & 0xF, rD,
1685 (lo16 >> 8) & 0xF, (lo16 >> 4) & 0xF,
1689 instr = XXXXXXXX(0xE, 0x3, 0x4, (hi16 >> 12) & 0xF, rD,
1690 (hi16 >> 8) & 0xF, (hi16 >> 4) & 0xF,
1699 Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
1700 Bool mode64, void* dispatch )
1702 UInt* p = (UInt*)buf;
1703 vassert(nbuf >= 32);
1704 vassert(mode64 == False);
1705 vassert(0 == (((HWord)buf) & 3));
1706 /* since we branch to lr(r13) to get back to dispatch: */
1707 vassert(dispatch == NULL);
1712 UInt rD = iregNo(i->ARMin.Alu.dst);
1713 UInt rN = iregNo(i->ARMin.Alu.argL);
1714 ARMRI84* argR = i->ARMin.Alu.argR;
1715 switch (i->ARMin.Alu.op) {
1716 case ARMalu_ADDS: /* fallthru */
1717 case ARMalu_ADD: subopc = X0100; break;
1718 case ARMalu_ADC: subopc = X0101; break;
1719 case ARMalu_SUBS: /* fallthru */
1720 case ARMalu_SUB: subopc = X0010; break;
1721 case ARMalu_SBC: subopc = X0110; break;
1722 case ARMalu_AND: subopc = X0000; break;
1723 case ARMalu_BIC: subopc = X1110; break;
1724 case ARMalu_OR: subopc = X1100; break;
1725 case ARMalu_XOR: subopc = X0001; break;
1728 instr = skeletal_RI84(argR);
1729 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1730 (subopc << 1) & 0xF, rN, rD);
1731 if (i->ARMin.Alu.op == ARMalu_ADDS || i->ARMin.Alu.op == ARMalu_SUBS) {
1732 instr |= 1<<20; /* set the S bit */
1739 HReg rD = iregNo(i->ARMin.Shift.dst);
1740 HReg rM = iregNo(i->ARMin.Shift.argL);
1741 ARMRI5* argR = i->ARMin.Shift.argR;
1742 switch (i->ARMin.Shift.op) {
1743 case ARMsh_SHL: subopc = X0000; break;
1744 case ARMsh_SHR: subopc = X0001; break;
1745 case ARMsh_SAR: subopc = X0010; break;
1748 instr = skeletal_RI5(argR);
1749 instr |= XXXXX__X(X1110,X0001,X1010,X0000,rD, /* _ _ */ rM);
1750 instr |= (subopc & 3) << 5;
1756 HReg rDst = iregNo(i->ARMin.Unary.dst);
1757 HReg rSrc = iregNo(i->ARMin.Unary.src);
1758 switch (i->ARMin.Unary.op) {
1760 instr = XXXXXXXX(X1110,X0001,X0110,X1111,
1761 rDst,X1111,X0001,rSrc);
1764 case ARMun_NEG: /* RSB rD,rS,#0 */
1765 instr = XXXXX___(X1110,0x2,0x6,rSrc,rDst);
1769 UInt subopc = X1111; /* MVN */
1771 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1772 (subopc << 1) & 0xF, 0, rDst);
1781 case ARMin_CmpOrTst: {
1782 UInt instr = skeletal_RI84(i->ARMin.CmpOrTst.argR);
1783 UInt subopc = i->ARMin.CmpOrTst.isCmp ? X1010 : X1000;
1785 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1786 ((subopc << 1) & 0xF) | 1,
1787 i->ARMin.CmpOrTst.argL, SBZ );
1792 UInt instr = skeletal_RI84(i->ARMin.Mov.src);
1793 UInt subopc = X1101; /* MOV */
1795 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1796 (subopc << 1) & 0xF, SBZ, i->ARMin.Mov.dst);
1801 p = imm32_to_iregNo( (UInt*)p, iregNo(i->ARMin.Imm32.dst),
1802 i->ARMin.Imm32.imm32 );
1806 case ARMin_LdSt8U: {
1810 if (i->tag == ARMin_LdSt32) {
1812 bL = i->ARMin.LdSt32.isLoad ? 1 : 0;
1813 am = i->ARMin.LdSt32.amode;
1814 rD = i->ARMin.LdSt32.rD;
1817 bL = i->ARMin.LdSt8U.isLoad ? 1 : 0;
1818 am = i->ARMin.LdSt8U.amode;
1819 rD = i->ARMin.LdSt8U.rD;
1821 if (am->tag == ARMam1_RI) {
1824 if (am->ARMam1.RI.simm13 < 0) {
1826 simm12 = -am->ARMam1.RI.simm13;
1829 simm12 = am->ARMam1.RI.simm13;
1831 vassert(simm12 >= 0 && simm12 <= 4095);
1832 instr = XXXXX___(X1110,X0101,BITS4(bP,bB,0,bL),
1833 iregNo(am->ARMam1.RI.reg),
1843 case ARMin_LdSt16: {
1844 HReg rD = i->ARMin.LdSt16.rD;
1845 UInt bS = i->ARMin.LdSt16.signedLoad ? 1 : 0;
1846 UInt bL = i->ARMin.LdSt16.isLoad ? 1 : 0;
1847 ARMAMode2* am = i->ARMin.LdSt16.amode;
1848 if (am->tag == ARMam2_RI) {
1849 HReg rN = am->ARMam2.RI.reg;
1851 UInt bP, imm8hi, imm8lo, instr;
1852 if (am->ARMam2.RI.simm9 < 0) {
1854 simm8 = -am->ARMam2.RI.simm9;
1857 simm8 = am->ARMam2.RI.simm9;
1859 vassert(simm8 >= 0 && simm8 <= 255);
1860 imm8hi = (simm8 >> 4) & 0xF;
1861 imm8lo = simm8 & 0xF;
1862 vassert(!(bL == 0 && bS == 1)); // "! signed store"
1863 /**/ if (bL == 0 && bS == 0) {
1865 instr = XXXXXXXX(X1110,X0001, BITS4(bP,1,0,0), iregNo(rN),
1866 iregNo(rD), imm8hi, X1011, imm8lo);
1870 else if (bL == 1 && bS == 0) {
1872 instr = XXXXXXXX(X1110,X0001, BITS4(bP,1,0,1), iregNo(rN),
1873 iregNo(rD), imm8hi, X1011, imm8lo);
1877 else if (bL == 1 && bS == 1) {
1880 else vassert(0); // ill-constructed insn
1890 IRJumpKind jk = i->ARMin.Goto.jk;
1891 ARMCondCode cond = i->ARMin.Goto.cond;
1892 UInt rnext = iregNo(i->ARMin.Goto.gnext);
1895 case Ijk_Ret: case Ijk_Call: case Ijk_Boring:
1896 break; /* no need to set GST in these common cases */
1898 trc = VEX_TRC_JMP_CLIENTREQ; break;
1899 case Ijk_Sys_int128:
1900 case Ijk_Sys_int129:
1901 case Ijk_Sys_int130:
1907 trc = VEX_TRC_JMP_NODECODE; break;
1909 trc = VEX_TRC_JMP_TINVAL; break;
1911 trc = VEX_TRC_JMP_NOREDIR; break;
1912 case Ijk_Sys_sysenter:
1916 case Ijk_Sys_syscall:
1917 trc = VEX_TRC_JMP_SYS_SYSCALL; break;
1923 // mov{cond} r8, #trc
1924 vassert(trc >= 0 && trc <= 255);
1925 instr = (cond << 28) | 0x03A08000 | (0xFF & (UInt)trc);
1928 // mov{cond} r0, rnext
1930 instr = (cond << 28) | 0x01A00000 | rnext;
1934 instr =(cond << 28) | 0x012FFF1E;
1939 UInt instr = skeletal_RI84(i->ARMin.CMov.src);
1940 UInt subopc = X1101; /* MOV */
1942 instr |= XXXXX___(i->ARMin.CMov.cond, (1 & (subopc >> 3)),
1943 (subopc << 1) & 0xF, SBZ, i->ARMin.CMov.dst);
1949 /* Decide on a scratch reg used to hold to the call address.
1950 This has to be done as per the comments in getRegUsage. */
1952 switch (i->ARMin.Call.nArgRegs) {
1953 case 0: scratchNo = 0; break;
1954 case 1: scratchNo = 1; break;
1955 case 2: scratchNo = 2; break;
1956 case 3: scratchNo = 3; break;
1957 case 4: scratchNo = 11; break;
1958 default: vassert(0);
1960 // r"scratchNo" = &target
1961 p = imm32_to_iregNo( (UInt*)p,
1962 scratchNo, (UInt)i->ARMin.Call.target );
1963 // blx{cond} r"scratchNo"
1964 instr = XXX___XX(i->ARMin.Call.cond, X0001, X0010, /*___*/
1966 instr |= 0xFFF << 8; // stick in the SBOnes
1971 /* E0000392 mul r0, r2, r3
1972 E0810392 umull r0(LO), r1(HI), r2, r3
1973 E0C10392 smull r0(LO), r1(HI), r2, r3
1975 switch (i->ARMin.Mul.op) {
1976 case ARMmul_PLAIN: *p++ = 0xE0000392; goto done;
1977 case ARMmul_ZX: *p++ = 0xE0810392; goto done;
1978 case ARMmul_SX: *p++ = 0xE0C10392; goto done;
1979 default: vassert(0);
1984 /* E1910F9F ldrex r0, [r1]
1985 E1F10F9F ldrexh r0, [r1]
1986 E1D10F9F ldrexb r0, [r1]
1988 switch (i->ARMin.LdrEX.szB) {
1989 case 4: *p++ = 0xE1910F9F; goto done;
1990 //case 2: *p++ = 0xE1F10F9F; goto done;
1991 case 1: *p++ = 0xE1D10F9F; goto done;
1997 /* E1820F91 strex r0, r1, [r2]
1998 E1E20F91 strexh r0, r1, [r2]
1999 E1C20F91 strexb r0, r1, [r2]
2001 switch (i->ARMin.StrEX.szB) {
2002 case 4: *p++ = 0xE1820F91; goto done;
2003 //case 2: *p++ = 0xE1E20F91; goto done;
2004 case 1: *p++ = 0xE1C20F91; goto done;
2009 case ARMin_VLdStD: {
2010 UInt dD = dregNo(i->ARMin.VLdStD.dD);
2011 UInt rN = iregNo(i->ARMin.VLdStD.amode->reg);
2012 Int simm11 = i->ARMin.VLdStD.amode->simm11;
2013 UInt off8 = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
2014 UInt bU = simm11 >= 0 ? 1 : 0;
2015 UInt bL = i->ARMin.VLdStD.isLoad ? 1 : 0;
2017 vassert(0 == (off8 & 3));
2019 vassert(0 == (off8 & 0xFFFFFF00));
2020 insn = XXXXXX__(0xE,X1101,BITS4(bU,0,0,bL),rN,dD,X1011);
2025 case ARMin_VLdStS: {
2026 UInt fD = fregNo(i->ARMin.VLdStS.fD);
2027 UInt rN = iregNo(i->ARMin.VLdStS.amode->reg);
2028 Int simm11 = i->ARMin.VLdStS.amode->simm11;
2029 UInt off8 = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
2030 UInt bU = simm11 >= 0 ? 1 : 0;
2031 UInt bL = i->ARMin.VLdStS.isLoad ? 1 : 0;
2034 vassert(0 == (off8 & 3));
2036 vassert(0 == (off8 & 0xFFFFFF00));
2037 insn = XXXXXX__(0xE,X1101,BITS4(bU,bD,0,bL),rN, (fD >> 1), X1010);
2043 UInt dN = dregNo(i->ARMin.VAluD.argL);
2044 UInt dD = dregNo(i->ARMin.VAluD.dst);
2045 UInt dM = dregNo(i->ARMin.VAluD.argR);
2046 UInt pqrs = X1111; /* undefined */
2047 switch (i->ARMin.VAluD.op) {
2048 case ARMvfp_ADD: pqrs = X0110; break;
2049 case ARMvfp_SUB: pqrs = X0111; break;
2050 case ARMvfp_MUL: pqrs = X0100; break;
2051 case ARMvfp_DIV: pqrs = X1000; break;
2054 vassert(pqrs != X1111);
2055 UInt bP = (pqrs >> 3) & 1;
2056 UInt bQ = (pqrs >> 2) & 1;
2057 UInt bR = (pqrs >> 1) & 1;
2058 UInt bS = (pqrs >> 0) & 1;
2059 UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,0,bQ,bR), dN, dD,
2060 X1011, BITS4(0,bS,0,0), dM);
2065 UInt dN = fregNo(i->ARMin.VAluS.argL);
2066 UInt dD = fregNo(i->ARMin.VAluS.dst);
2067 UInt dM = fregNo(i->ARMin.VAluS.argR);
2071 UInt pqrs = X1111; /* undefined */
2072 switch (i->ARMin.VAluS.op) {
2073 case ARMvfp_ADD: pqrs = X0110; break;
2074 case ARMvfp_SUB: pqrs = X0111; break;
2075 case ARMvfp_MUL: pqrs = X0100; break;
2076 case ARMvfp_DIV: pqrs = X1000; break;
2079 vassert(pqrs != X1111);
2080 UInt bP = (pqrs >> 3) & 1;
2081 UInt bQ = (pqrs >> 2) & 1;
2082 UInt bR = (pqrs >> 1) & 1;
2083 UInt bS = (pqrs >> 0) & 1;
2084 UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,bD,bQ,bR),
2085 (dN >> 1), (dD >> 1),
2086 X1010, BITS4(bN,bS,bM,0), (dM >> 1));
2090 case ARMin_VUnaryD: {
2091 UInt dD = dregNo(i->ARMin.VUnaryD.dst);
2092 UInt dM = dregNo(i->ARMin.VUnaryD.src);
2094 switch (i->ARMin.VUnaryD.op) {
2096 insn = XXXXXXXX(0xE, X1110,X1011,X0000,dD,X1011,X0100,dM);
2099 insn = XXXXXXXX(0xE, X1110,X1011,X0000,dD,X1011,X1100,dM);
2102 insn = XXXXXXXX(0xE, X1110,X1011,X0001,dD,X1011,X0100,dM);
2105 insn = XXXXXXXX(0xE, X1110,X1011,X0001,dD,X1011,X1100,dM);
2113 case ARMin_VUnaryS: {
2114 UInt fD = fregNo(i->ARMin.VUnaryS.dst);
2115 UInt fM = fregNo(i->ARMin.VUnaryS.src);
2117 switch (i->ARMin.VUnaryS.op) {
2119 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
2120 (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
2124 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
2125 (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
2129 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
2130 (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
2134 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
2135 (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
2145 UInt dD = dregNo(i->ARMin.VCmpD.argL);
2146 UInt dM = dregNo(i->ARMin.VCmpD.argR);
2147 UInt insn = XXXXXXXX(0xE, X1110, X1011, X0100, dD, X1011, X0100, dM);
2148 *p++ = insn; /* FCMPD dD, dM */
2149 *p++ = 0xEEF1FA10; /* FMSTAT */
2152 case ARMin_VCMovD: {
2153 UInt cc = (UInt)i->ARMin.VCMovD.cond;
2154 UInt dD = dregNo(i->ARMin.VCMovD.dst);
2155 UInt dM = dregNo(i->ARMin.VCMovD.src);
2156 vassert(cc < 16 && cc != ARMcc_AL);
2157 UInt insn = XXXXXXXX(cc, X1110,X1011,X0000,dD,X1011,X0100,dM);
2161 case ARMin_VCMovS: {
2162 UInt cc = (UInt)i->ARMin.VCMovS.cond;
2163 UInt fD = fregNo(i->ARMin.VCMovS.dst);
2164 UInt fM = fregNo(i->ARMin.VCMovS.src);
2165 vassert(cc < 16 && cc != ARMcc_AL);
2166 UInt insn = XXXXXXXX(cc, X1110, BITS4(1,(fD & 1),1,1),
2167 X0000,(fD >> 1),X1010,
2168 BITS4(0,1,(fM & 1),0), (fM >> 1));
2172 case ARMin_VCvtSD: {
2173 if (i->ARMin.VCvtSD.sToD) {
2174 UInt dD = dregNo(i->ARMin.VCvtSD.dst);
2175 UInt fM = fregNo(i->ARMin.VCvtSD.src);
2176 UInt insn = XXXXXXXX(0xE, X1110, X1011, X0111, dD, X1010,
2177 BITS4(1,1, (fM & 1), 0),
2182 UInt fD = fregNo(i->ARMin.VCvtSD.dst);
2183 UInt dM = dregNo(i->ARMin.VCvtSD.src);
2184 UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1),
2192 case ARMin_VXferD: {
2193 UInt dD = dregNo(i->ARMin.VXferD.dD);
2194 UInt rHi = iregNo(i->ARMin.VXferD.rHi);
2195 UInt rLo = iregNo(i->ARMin.VXferD.rLo);
2196 /* vmov dD, rLo, rHi is
2197 E C 4 rHi rLo B (0,0,dD[4],1) dD[3:0]
2198 vmov rLo, rHi, dD is
2199 E C 5 rHi rLo B (0,0,dD[4],1) dD[3:0]
2202 = XXXXXXXX(0xE, 0xC, i->ARMin.VXferD.toD ? 4 : 5,
2204 BITS4(0,0, ((dD >> 4) & 1), 1), (dD & 0xF));
2208 case ARMin_VXferS: {
2209 UInt fD = fregNo(i->ARMin.VXferS.fD);
2210 UInt rLo = iregNo(i->ARMin.VXferS.rLo);
2212 E E 0 fD[4:1] rLo A (fD[0],0,0,1) 0
2214 E E 1 fD[4:1] rLo A (fD[0],0,0,1) 0
2217 = XXXXXXXX(0xE, 0xE, i->ARMin.VXferS.toS ? 0 : 1,
2218 (fD >> 1) & 0xF, rLo, 0xA,
2219 BITS4((fD & 1),0,0,1), 0);
2223 case ARMin_VCvtID: {
2224 Bool iToD = i->ARMin.VCvtID.iToD;
2225 Bool syned = i->ARMin.VCvtID.syned;
2226 if (iToD && syned) {
2227 // FSITOD: I32S-in-freg to F64-in-dreg
2228 UInt regF = fregNo(i->ARMin.VCvtID.src);
2229 UInt regD = dregNo(i->ARMin.VCvtID.dst);
2230 UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
2231 X1011, BITS4(1,1,(regF & 1),0),
2236 if (iToD && (!syned)) {
2237 // FUITOD: I32U-in-freg to F64-in-dreg
2238 UInt regF = fregNo(i->ARMin.VCvtID.src);
2239 UInt regD = dregNo(i->ARMin.VCvtID.dst);
2240 UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
2241 X1011, BITS4(0,1,(regF & 1),0),
2246 if ((!iToD) && syned) {
2247 // FTOSID: F64-in-dreg to I32S-in-freg
2248 UInt regD = dregNo(i->ARMin.VCvtID.src);
2249 UInt regF = fregNo(i->ARMin.VCvtID.dst);
2250 UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
2251 X1101, (regF >> 1) & 0xF,
2252 X1011, X0100, regD);
2256 if ((!iToD) && (!syned)) {
2257 // FTOUID: F64-in-dreg to I32U-in-freg
2258 UInt regD = dregNo(i->ARMin.VCvtID.src);
2259 UInt regF = fregNo(i->ARMin.VCvtID.dst);
2260 UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
2261 X1100, (regF >> 1) & 0xF,
2262 X1011, X0100, regD);
2270 Bool toFPSCR = i->ARMin.FPSCR.toFPSCR;
2271 HReg iReg = iregNo(i->ARMin.FPSCR.iReg);
2273 /* fmxr fpscr, iReg is EEE1 iReg A10 */
2274 *p++ = 0xEEE10A10 | ((iReg & 0xF) << 12);
2277 goto bad; // FPSCR -> iReg case currently ATC
2279 case ARMin_MFence: {
2280 *p++ = 0xEE070F9A; /* mcr 15,0,r0,c7,c10,4 (DSB) */
2281 *p++ = 0xEE070FBA; /* mcr 15,0,r0,c7,c10,5 (DMB) */
2282 *p++ = 0xEE070F95; /* mcr 15,0,r0,c7,c5,4 (ISB) */
2291 vpanic("emit_ARMInstr");
2295 vassert(((UChar*)p) - &buf[0] <= 32);
2296 return ((UChar*)p) - &buf[0];
2322 /*---------------------------------------------------------------*/
2323 /*--- end host_arm_defs.c ---*/
2324 /*---------------------------------------------------------------*/