--- /dev/null
+
+/*---------------------------------------------------------------*/
+/*--- ---*/
+/*--- This file (host-arm/hdefs.c) is ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
+/*--- ---*/
+/*---------------------------------------------------------------*/
+
+/*
+ This file is part of LibVEX, a library for dynamic binary
+ instrumentation and translation.
+
+ Copyright (C) 2004 OpenWorks, LLP.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; Version 2 dated June 1991 of the
+ license.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
+ for damages. See the GNU General Public License for more details.
+
+ Neither the names of the U.S. Department of Energy nor the
+ University of California nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without prior written permission.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex.h"
+#include "libvex_trc_values.h"
+
+#include "main/vex_util.h"
+#include "host-generic/h_generic_regs.h"
+#include "host-arm/hdefs.h"
+
+
+
+/* --------- Registers. --------- */
+
+/* The usual HReg abstraction. There are 8 real int regs,
+ 6 real float regs, and 0 real vector regs.
+*/
+
+
+/* --------- Registers. --------- */
+
+void ppHRegARM ( HReg reg ) {
+ Int r;
+ static HChar* ireg32_names[16]
+ = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
+
+ /* Be generic for all virtual regs. */
+ if (hregIsVirtual(reg)) {
+ ppHReg(reg);
+ return;
+ }
+ /* But specific for real regs. */
+ switch (hregClass(reg)) {
+ case HRcInt32:
+ r = hregNumber(reg);
+ vassert(r >= 0 && r < 16);
+ vex_printf("%s", ireg32_names[r]);
+ return;
+ default:
+ vpanic("ppHRegARM");
+ }
+}
+
+HReg hregARM_R0 ( void ) { return mkHReg(0, HRcInt32, False); }
+HReg hregARM_R1 ( void ) { return mkHReg(1, HRcInt32, False); }
+HReg hregARM_R2 ( void ) { return mkHReg(2, HRcInt32, False); }
+HReg hregARM_R3 ( void ) { return mkHReg(3, HRcInt32, False); }
+HReg hregARM_R4 ( void ) { return mkHReg(4, HRcInt32, False); }
+HReg hregARM_R5 ( void ) { return mkHReg(5, HRcInt32, False); }
+HReg hregARM_R6 ( void ) { return mkHReg(6, HRcInt32, False); }
+HReg hregARM_R7 ( void ) { return mkHReg(7, HRcInt32, False); }
+HReg hregARM_R8 ( void ) { return mkHReg(8, HRcInt32, False); }
+HReg hregARM_R9 ( void ) { return mkHReg(9, HRcInt32, False); }
+HReg hregARM_R10 ( void ) { return mkHReg(10, HRcInt32, False); }
+HReg hregARM_R11 ( void ) { return mkHReg(11, HRcInt32, False); }
+HReg hregARM_R12 ( void ) { return mkHReg(12, HRcInt32, False); }
+HReg hregARM_R13 ( void ) { return mkHReg(13, HRcInt32, False); }
+HReg hregARM_R14 ( void ) { return mkHReg(14, HRcInt32, False); }
+HReg hregARM_R15 ( void ) { return mkHReg(15, HRcInt32, False); }
+
+void getAllocableRegs_ARM ( Int* nregs, HReg** arr ) {
+ *nregs = 20;
+ *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
+ (*arr)[0] = hregARM_R0();
+ (*arr)[1] = hregARM_R1();
+ (*arr)[2] = hregARM_R2();
+ (*arr)[3] = hregARM_R3();
+ (*arr)[4] = hregARM_R4();
+ (*arr)[5] = hregARM_R5();
+ (*arr)[6] = hregARM_R6();
+ (*arr)[7] = hregARM_R7();
+ (*arr)[8] = hregARM_R8();
+ (*arr)[9] = hregARM_R9();
+ (*arr)[10] = hregARM_R10();
+ (*arr)[11] = hregARM_R11();
+ (*arr)[12] = hregARM_R12();
+ (*arr)[13] = hregARM_R13();
+ (*arr)[14] = hregARM_R14();
+ (*arr)[15] = hregARM_R15();
+}
+
+
+
+/* --------- Condition codes, ARM encoding. --------- */
+
+HChar* showARMCondCode ( ARMCondCode cond ) {
+ switch (cond) {
+ case ARMccEQ: return "eq";
+ case ARMccNE: return "ne";
+ case ARMccHS: return "hs";
+ case ARMccLO: return "lo";
+ case ARMccMI: return "mi";
+ case ARMccPL: return "pl";
+ case ARMccVS: return "vs";
+ case ARMccVC: return "vc";
+ case ARMccHI: return "hi";
+ case ARMccLS: return "ls";
+ case ARMccGE: return "ge";
+ case ARMccLT: return "lt";
+ case ARMccGT: return "gt";
+ case ARMccLE: return "le";
+ case ARMccAL: return "al"; // default
+ case ARMccNV: return "nv";
+ default: vpanic("showARMCondCode");
+ }
+}
+
+
+/* --------- ARMAMode1: memory address expressions. --------- */
+
+ARMAMode1* ARMAMode1_I12A ( ARMImm12A imm ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_I12A;
+ am->ARMam1.I12A.imm = imm;
+ return am;
+}
+ARMAMode1* ARMAMode1_ShlI ( HReg Rm, ARMImm5 imm ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_ShlI;
+ am->ARMam1.ShlI.Rm = Rm;
+ am->ARMam1.ShlI.imm = imm;
+ return am;
+}
+ARMAMode1* ARMAMode1_ShrI ( HReg Rm, ARMImm5 imm ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_ShrI;
+ am->ARMam1.ShrI.Rm = Rm;
+ am->ARMam1.ShrI.imm = imm;
+ return am;
+}
+ARMAMode1* ARMAMode1_SarI ( HReg Rm, ARMImm5 imm ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_SarI;
+ am->ARMam1.SarI.Rm = Rm;
+ am->ARMam1.SarI.imm = imm;
+ return am;
+}
+ARMAMode1* ARMAMode1_ShlR ( HReg Rm, HReg Rs ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_ShlR;
+ am->ARMam1.ShlR.Rm = Rm;
+ am->ARMam1.ShlR.Rs = Rs;
+ return am;
+}
+ARMAMode1* ARMAMode1_ShrR ( HReg Rm, HReg Rs ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_ShrR;
+ am->ARMam1.ShrR.Rm = Rm;
+ am->ARMam1.ShrR.Rs = Rs;
+ return am;
+}
+ARMAMode1* ARMAMode1_SarR ( HReg Rm, HReg Rs ) {
+ ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
+ am->tag = ARMam1_SarR;
+ am->ARMam1.SarR.Rm = Rm;
+ am->ARMam1.SarR.Rs = Rs;
+ return am;
+}
+
+ARMAMode1* dopyARMAMode1 ( ARMAMode1* am ) {
+ switch (am->tag) {
+ case ARMam1_I12A:
+ return ARMAMode1_I12A( am->ARMam1.I12A.imm );
+ case ARMam1_ShlI:
+ return ARMAMode1_ShlI( am->ARMam1.ShlI.Rm, am->ARMam1.ShlI.imm );
+ case ARMam1_ShrI:
+ return ARMAMode1_ShrI( am->ARMam1.ShrI.Rm, am->ARMam1.ShrI.imm );
+ case ARMam1_SarI:
+ return ARMAMode1_SarI( am->ARMam1.SarI.Rm, am->ARMam1.SarI.imm );
+ case ARMam1_ShlR:
+ return ARMAMode1_ShlR( am->ARMam1.ShlR.Rm, am->ARMam1.ShlR.Rs );
+ case ARMam1_ShrR:
+ return ARMAMode1_ShrR( am->ARMam1.ShrR.Rm, am->ARMam1.ShrR.Rs );
+ case ARMam1_SarR:
+ return ARMAMode1_SarR( am->ARMam1.SarR.Rm, am->ARMam1.SarR.Rs );
+ default:
+ vpanic("dopyARMAMode1");
+ }
+}
+
+void ppARMAMode1 ( ARMAMode1* am ) {
+ switch (am->tag) {
+ case ARMam1_I12A:
+ case ARMam1_ShlI:
+ case ARMam1_ShrI:
+ case ARMam1_SarI:
+ case ARMam1_ShlR:
+ case ARMam1_ShrR:
+ case ARMam1_SarR:
+ vex_printf("ppARMAMode1: Not implemented");
+ break;
+ default:
+ vpanic("ppARMAMode1");
+ }
+}
+
+/*
+static void addRegUsage_ARMAMode1 ( HRegUsage* u, ARMAMode1* am ) {
+static void mapRegs_ARMAMode1 ( HRegRemap* m, ARMAMode1* am ) {
+*/
+
+
+/* --------- ARMAMode2: memory address expressions. --------- */
+
+ARMAMode2* ARMAMode2_RI ( HReg Rn, ARMImm12 imm ) {
+ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
+ am->tag = ARMam2_RI;
+ am->ARMam2.RI.Rn = Rn;
+ am->ARMam2.RI.imm = imm;
+ return am;
+}
+ARMAMode2* ARMAMode2_RR ( HReg Rn, HReg Rm ) {
+ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
+ am->tag = ARMam2_RR;
+ am->ARMam2.RR.Rn = Rn;
+ am->ARMam2.RR.Rm = Rm;
+ return am;
+}
+ARMAMode2* ARMAMode2_RRS ( HReg Rn, HReg Rm, ARMImm5 shift ) {
+ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
+ am->tag = ARMam2_RRS;
+ am->ARMam2.RRS.Rn = Rn;
+ am->ARMam2.RRS.Rm = Rm;
+ am->ARMam2.RRS.shift = shift;
+ return am;
+}
+
+ARMAMode2* dopyARMAMode2 ( ARMAMode2* am ) {
+ switch (am->tag) {
+ case ARMam2_RI:
+ return ARMAMode2_RI( am->ARMam2.RI.Rn, am->ARMam2.RI.imm );
+ case ARMam2_RR:
+ return ARMAMode2_RR( am->ARMam2.RR.Rn, am->ARMam2.RR.Rm );
+ case ARMam2_RRS:
+ return ARMAMode2_RRS( am->ARMam2.RRS.Rn, am->ARMam2.RRS.Rm,
+ am->ARMam2.RRS.shift );
+ default:
+ vpanic("dopyARMAMode2");
+ }
+}
+
+void ppARMAMode2 ( ARMAMode2* am ) {
+ switch (am->tag) {
+ case ARMam2_RI:
+ case ARMam2_RR:
+ case ARMam2_RRS:
+ vex_printf("ppARMAMode2: Not implemented");
+ break;
+ default:
+ vpanic("ppARMAMode2");
+ }
+}
+
+/*
+static void addRegUsage_ARMAMode2 ( HRegUsage* u, ARMAMode1* am ) {
+static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode1* am ) {
+*/
+
+
+/* --------- ARMAMode3: memory address expressions. --------- */
+
+ARMAMode3* ARMAMode3_RI ( HReg Rn, ARMImm8 imm ) {
+ ARMAMode3* am = LibVEX_Alloc(sizeof(ARMAMode3));
+ am->tag = ARMam3_RI;
+ am->ARMam3.RI.Rn = Rn;
+ am->ARMam3.RI.imm = imm;
+ return am;
+}
+ARMAMode3* ARMAMode3_RR ( HReg Rn, HReg Rm ) {
+ ARMAMode3* am = LibVEX_Alloc(sizeof(ARMAMode3));
+ am->tag = ARMam3_RR;
+ am->ARMam3.RR.Rn = Rn;
+ am->ARMam3.RR.Rm = Rm;
+ return am;
+}
+
+ARMAMode3* dopyARMAMode3 ( ARMAMode3* am ) {
+ switch (am->tag) {
+ case ARMam3_RI:
+ return ARMAMode3_RI( am->ARMam3.RI.Rn, am->ARMam3.RI.imm );
+ case ARMam3_RR:
+ return ARMAMode3_RR( am->ARMam3.RR.Rn, am->ARMam3.RR.Rm );
+ default:
+ vpanic("dopyARMAMode3");
+ }
+}
+
+void ppARMAMode3 ( ARMAMode3* am ) {
+ switch (am->tag) {
+ case ARMam3_RI:
+ case ARMam3_RR:
+ vex_printf("ppARMAMode3: Not implemented");
+ break;
+ default:
+ vpanic("ppARMAMode3");
+ }
+}
+
+/*
+static void addRegUsage_ARMAMode1 ( HRegUsage* u, ARMAMode2* am ) {
+static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode2* am ) {
+*/
+
+/* ------ Branch destination ------ */
+
+ARMBranchDest* ARMBranchDest_Imm ( ARMImm24 imm24 ) {
+ ARMBranchDest* branch_dest = LibVEX_Alloc(sizeof(ARMBranchDest));
+ branch_dest->tag = ARMbdImm;
+ branch_dest->ARMbd.Imm.imm24 = imm24;
+ return branch_dest;
+}
+ARMBranchDest* ARMBranchDest_Reg ( HReg reg ) {
+ ARMBranchDest* branch_dest = LibVEX_Alloc(sizeof(ARMBranchDest));
+ branch_dest->tag = ARMbdReg;
+ branch_dest->ARMbd.Reg.reg = reg;
+ return branch_dest;
+}
+
+void ppARMBranchDest ( ARMBranchDest* branch_dest ) {
+ switch (branch_dest->tag) {
+ case ARMbdImm:
+ case ARMbdReg:
+ vex_printf("ppARMBranchDest: Not implemented");
+ break;
+ default:
+ vpanic("ppX86RM");
+ }
+}
+
+
+
+
+/* --------- Instructions. --------- */
+
+HChar* showARMAluOp ( ARMAluOp op ) {
+ switch (op) {
+ case ARMalu_And: return "and";
+ case ARMalu_Orr: return "orr";
+ case ARMalu_Eor: return "eor";
+ case ARMalu_Sub: return "sub";
+ case ARMalu_Rsb: return "rsb";
+ case ARMalu_Add: return "add";
+ case ARMalu_Adc: return "adc";
+ case ARMalu_Sbc: return "sbc";
+ case ARMalu_Rsc: return "rsc";
+ case ARMalu_Tst: return "tst";
+ case ARMalu_Teq: return "teq";
+ case ARMalu_Cmp: return "cmp";
+ case ARMalu_Cmn: return "cmn";
+ case ARMalu_Mov: return "mov";
+ case ARMalu_Mvn: return "mvn";
+ case ARMalu_Bic: return "vic";
+ default: vpanic("showARMAluOp");
+ }
+}
+
+/* --- Addressing Mode 1 --- */
+ARMInstr* ARMInstr_DPCmp ( ARMAluOp op, HReg Rn,
+ ARMAMode1 shifter_op ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_DPCmp;
+ i->ARMin.DPCmp.op = op;
+ i->ARMin.DPCmp.Rn = Rn;
+ i->ARMin.DPCmp.shifter_op = shifter_op;
+ return i;
+}
+
+ARMInstr* ARMInstr_DPInstr1 ( ARMAluOp op, HReg Rd,
+ ARMAMode1 shifter_op ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_DPInstr1;
+ i->ARMin.DPInstr1.op = op;
+ i->ARMin.DPInstr1.Rd = Rd;
+ i->ARMin.DPInstr1.shifter_op = shifter_op;
+ return i;
+}
+
+ARMInstr* ARMInstr_DPInstr2 ( ARMAluOp op, HReg Rd, HReg Rn,
+ ARMAMode1 shifter_op ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_DPInstr2;
+ i->ARMin.DPInstr2.op = op;
+ i->ARMin.DPInstr2.Rd = Rd;
+ i->ARMin.DPInstr2.Rn = Rn;
+ i->ARMin.DPInstr2.shifter_op = shifter_op;
+ return i;
+}
+
+/* --- Addressing Mode 2 --- */
+ARMInstr* ARMInstr_LoadUB ( HReg Rd, ARMAMode2 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_LoadUB;
+ i->ARMin.LoadUB.Rd = Rd;
+ i->ARMin.LoadUB.addr_mode = addr_mode;
+ return i;
+}
+
+ARMInstr* ARMInstr_StoreB ( HReg Rd, ARMAMode2 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_StoreB;
+ i->ARMin.StoreB.Rd = Rd;
+ i->ARMin.StoreB.addr_mode = addr_mode;
+ return i;
+}
+
+ARMInstr* ARMInstr_LoadW ( HReg Rd, ARMAMode2 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_LoadW;
+ i->ARMin.LoadW.Rd = Rd;
+ i->ARMin.LoadW.addr_mode = addr_mode;
+ return i;
+}
+
+ARMInstr* ARMInstr_StoreW ( HReg Rd, ARMAMode2 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_StoreW;
+ i->ARMin.StoreW.Rd = Rd;
+ i->ARMin.StoreW.addr_mode = addr_mode;
+ return i;
+}
+
+/* --- Addressing Mode 3 --- */
+ARMInstr* ARMInstr_LoadSB ( HReg Rd, ARMAMode3 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_LoadSB;
+ i->ARMin.LoadSB.Rd = Rd;
+ i->ARMin.LoadSB.addr_mode = addr_mode;
+ return i;
+}
+
+ARMInstr* ARMInstr_LoadUH ( HReg Rd, ARMAMode3 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_LoadUH;
+ i->ARMin.LoadUH.Rd = Rd;
+ i->ARMin.LoadUH.addr_mode = addr_mode;
+ return i;
+}
+
+ARMInstr* ARMInstr_LoadSH ( HReg Rd, ARMAMode3 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_LoadSH;
+ i->ARMin.LoadSH.Rd = Rd;
+ i->ARMin.LoadSH.addr_mode = addr_mode;
+ return i;
+}
+
+ARMInstr* ARMInstr_StoreH ( HReg Rd, ARMAMode3 addr_mode ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_StoreH;
+ i->ARMin.StoreH.Rd = Rd;
+ i->ARMin.StoreH.addr_mode = addr_mode;
+ return i;
+}
+
+/* --- Branch --- */
+ARMInstr* ARMInstr_Branch ( ARMCondCode cond, ARMBranchDest dest ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_Branch;
+ i->ARMin.Branch.cond = cond;
+ i->ARMin.Branch.dest = dest;
+ return i;
+}
+
+ARMInstr* ARMInstr_BranchL ( ARMBranchDest dest ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_BranchL;
+ i->ARMin.BranchL.dest = dest;
+ return i;
+}
+
+/* --- Literal --- */
+ARMInstr* ARMInstr_Literal ( HReg reg, ARMImm12A imm12a ) {
+ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
+ i->tag = ARMin_Literal;
+ i->ARMin.Literal.reg = reg;
+ i->ARMin.Literal.imm12a = imm12a;
+ return i;
+}
+
+
+void ppARMInstr ( ARMInstr* i ) {
+ switch (i->tag) {
+ case ARMin_DPCmp:
+ case ARMin_DPInstr1:
+ case ARMin_DPInstr2:
+ case ARMin_LoadUB:
+ case ARMin_StoreB:
+ case ARMin_LoadW:
+ case ARMin_StoreW:
+ case ARMin_LoadSB:
+ case ARMin_LoadUH:
+ case ARMin_LoadSH:
+ case ARMin_StoreH:
+ case ARMin_Branch:
+ case ARMin_BranchL:
+ case ARMin_Literal:
+ vex_printf("ppARMInstr: Not implemented");
+ break;
+
+ default:
+ vpanic("ppARMInstr");
+ }
+}
+
+
+
+
+/* --------- Helpers for register allocation. --------- */
+
+void getRegUsage_ARMInstr ( HRegUsage* u, ARMInstr* i ) {
+// Bool unary;
+ initHRegUsage(u);
+ switch (i->tag) {
+ case ARMin_DPCmp:
+ case ARMin_DPInstr1:
+ case ARMin_DPInstr2:
+ case ARMin_LoadUB:
+ case ARMin_StoreB:
+ case ARMin_LoadW:
+ case ARMin_StoreW:
+ case ARMin_LoadSB:
+ case ARMin_LoadUH:
+ case ARMin_LoadSH:
+ case ARMin_StoreH:
+ case ARMin_Branch:
+ case ARMin_BranchL:
+ case ARMin_Literal:
+
+ default:
+ ppARMInstr(i);
+ vpanic("getRegUsage_ARMInstr");
+ }
+}
+
+
+/* local helper */
+#if 0
+static void mapReg(HRegRemap* m, HReg* r) {
+ *r = lookupHRegRemap(m, *r);
+}
+#endif
+
+void mapRegs_ARMInstr ( HRegRemap* m, ARMInstr* i ) {
+ switch (i->tag) {
+ case ARMin_DPCmp:
+ case ARMin_DPInstr1:
+ case ARMin_DPInstr2:
+ case ARMin_LoadUB:
+ case ARMin_StoreB:
+ case ARMin_LoadW:
+ case ARMin_StoreW:
+ case ARMin_LoadSB:
+ case ARMin_LoadUH:
+ case ARMin_LoadSH:
+ case ARMin_StoreH:
+ case ARMin_Branch:
+ case ARMin_BranchL:
+ case ARMin_Literal:
+
+ default:
+ ppARMInstr(i);
+ vpanic("getRegUsage_ARMInstr");
+ }
+}
+
+/* Figure out if i represents a reg-reg move, and if so assign the
+ source and destination to *src and *dst. If in doubt say No. Used
+ by the register allocator to do move coalescing.
+*/
+Bool isMove_ARMInstr ( ARMInstr* i, HReg* src, HReg* dst ) {
+ return False; // No optimisations for now...
+}
+
+
+/* Generate x86 spill/reload instructions under the direction of the
+ register allocator. Note it's critical these don't write the
+ condition codes. */
+
+ARMInstr* genSpill_ARM ( HReg rreg, Int offsetB ) {
+// ARMAMode1* am;
+ vassert(offsetB >= 0);
+ vassert(!hregIsVirtual(rreg));
+
+ switch (hregClass(rreg)) {
+
+ default:
+ ppHRegClass(hregClass(rreg));
+ vpanic("genSpill_ARM: unimplemented regclass");
+ }
+}
+
+ARMInstr* genReload_ARM ( HReg rreg, Int offsetB ) {
+// ARMAMode1* am;
+ vassert(offsetB >= 0);
+ vassert(!hregIsVirtual(rreg));
+
+ switch (hregClass(rreg)) {
+
+ default:
+ ppHRegClass(hregClass(rreg));
+ vpanic("genReload_ARM: unimplemented regclass");
+ }
+}
+
+
+/* Emit an instruction into buf and return the number of bytes used.
+ Note that buf is not the insn's final place, and therefore it is
+ imperative to emit position-independent code. */
+
+Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i ) {
+// UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
+
+// UInt xtra;
+ UChar* p = &buf[0];
+// UChar* ptmp;
+ vassert(nbuf >= 32);
+
+ switch (i->tag) {
+ case ARMin_DPCmp:
+ case ARMin_DPInstr1:
+ case ARMin_DPInstr2:
+ case ARMin_LoadUB:
+ case ARMin_StoreB:
+ case ARMin_LoadW:
+ case ARMin_StoreW:
+ case ARMin_LoadSB:
+ case ARMin_LoadUH:
+ case ARMin_LoadSH:
+ case ARMin_StoreH:
+ case ARMin_Branch:
+ case ARMin_BranchL:
+ case ARMin_Literal:
+ default:
+ goto bad;
+ }
+
+ bad:
+ ppARMInstr(i);
+ vpanic("emit_ARMInstr");
+ /*NOTREACHED*/
+
+// done:
+ vassert(p - &buf[0] <= 32);
+ return p - &buf[0];
+}
+
+
+/*---------------------------------------------------------------*/
+/*--- end host-x86/hdefs.c ---*/
+/*---------------------------------------------------------------*/
/* --- Addressing Mode 1 --- */
typedef
enum {
- ARMam_I12A, /* Imm12A: extended (rotated) immedate */
- ARMam_ShlI, /* ShlI reg Imm5 */
- ARMam_ShrI, /* ShrI reg Imm5 */
- ARMam_SarI, /* SarI reg Imm5 */
- ARMam_ShlR, /* ShlR reg reg */
- ARMam_ShrR, /* ShrR reg reg */
- ARMam_SarR, /* SarR reg reg */
+ ARMam1_I12A, /* Imm12A: extended (rotated) immedate */
+ ARMam1_ShlI, /* ShlI reg Imm5 */
+ ARMam1_ShrI, /* ShrI reg Imm5 */
+ ARMam1_SarI, /* SarI reg Imm5 */
+ ARMam1_ShlR, /* ShlR reg reg */
+ ARMam1_ShrR, /* ShrR reg reg */
+ ARMam1_SarR, /* SarR reg reg */
}
ARMAMode1Tag;
HReg Rm;
HReg Rs;
} SarR;
- } ARMam;
+ } ARMam1;
}
ARMAMode1;
extern ARMAMode1* ARMAMode1_I12A ( ARMImm12A );
-
extern ARMAMode1* ARMAMode1_ShlI ( HReg, ARMImm5 );
extern ARMAMode1* ARMAMode1_ShrI ( HReg, ARMImm5 );
extern ARMAMode1* ARMAMode1_SarI ( HReg, ARMImm5 );
/* --- Addressing Mode 2 --- */
typedef
enum {
- ARMam_RI12, /* Reg +/- Imm12 */
- ARMam_RR2, /* Reg +/- Reg */
- ARMam_RRS, /* Reg +/- (Reg << Imm5) */
+ ARMam2_RI, /* Reg +/- Imm12 */
+ ARMam2_RR, /* Reg +/- Reg */
+ ARMam2_RRS, /* Reg +/- (Reg << Imm5) */
}
ARMAMode2Tag;
HReg Rm;
ARMImm5 shift;
} RRS;
- } ARMam;
+ } ARMam2;
}
ARMAMode2;
-extern ARMAMode2* ARMAMode2_RI12 ( HReg, Int );
-extern ARMAMode2* ARMAMode2_RR2 ( HReg, HReg );
-extern ARMAMode2* ARMAMode2_RRS ( HReg, HReg, Int );
+extern ARMAMode2* ARMAMode2_RI ( HReg, ARMImm12 );
+extern ARMAMode2* ARMAMode2_RR ( HReg, HReg );
+extern ARMAMode2* ARMAMode2_RRS ( HReg, HReg, ARMImm5 );
-extern ARMAMode2* dopyARMMode2 ( ARMAMode2* );
+extern ARMAMode2* dopyARMAMode2 ( ARMAMode2* );
extern void ppARMAMode2 ( ARMAMode2* );
/* --- Addressing Mode 3 --- */
typedef
enum {
- ARMam_RI8, /* Reg +/- Imm8 */
- ARMam_RR3, /* Reg +/- Reg */
+ ARMam3_RI, /* Reg +/- Imm8 */
+ ARMam3_RR, /* Reg +/- Reg */
}
ARMAMode3Tag;
ARMAMode3Tag tag;
union {
struct {
- HReg reg;
+ HReg Rn;
ARMImm8 imm;
} RI;
struct {
HReg Rn;
HReg Rm;
} RR;
- } ARMam;
+ } ARMam3;
}
ARMAMode3;
-extern ARMAMode3* ARMAMode3_RI8 ( HReg, Int );
-extern ARMAMode3* ARMAMode3_RR3 ( HReg, HReg );
+extern ARMAMode3* ARMAMode3_RI ( HReg, ARMImm8 );
+extern ARMAMode3* ARMAMode3_RR ( HReg, HReg );
extern ARMAMode3* dopyARMAMode3 ( ARMAMode3* );
/* ------ Branch destination ------ */
typedef
enum {
- ARMbdImm24,
+ ARMbdImm,
ARMbdReg
}
ARMBranchTag;
ARMBranchTag tag;
union {
struct {
- ARMImm24 imm;
- } Imm24;
+ ARMImm24 imm24;
+ } Imm;
struct {
HReg reg;
} Reg;
}
ARMBranchDest;
+extern ARMBranchDest* ARMBranchDest_Imm ( ARMImm24 );
+extern ARMBranchDest* ARMBranchDest_Reg ( HReg );
+
+extern void ppARMBranchDest ( ARMBranchDest* );
/* --------- Instructions. --------- */
/* --- DPI's --- */
typedef
enum {
- ARMalu_And, ARMalu_Orr, ARMalu_Eor, // Logic
+ ARMalu_And, ARMalu_Orr, ARMalu_Eor, ARMalu_Bic, // Logic
ARMalu_Sub, ARMalu_Rsb, ARMalu_Add, ARMalu_Adc, ARMalu_Sbc, ARMalu_Rsc, // Arith
ARMalu_Tst, ARMalu_Teq, ARMalu_Cmp, ARMalu_Cmn, // test
- ARMalu_Mov, ARMalu_Mvn, // Move
- ARMalu_Bic // Bit clear
+ ARMalu_Mov, ARMalu_Mvn // Move
}
ARMAluOp;
} StoreH;
+ /* Branch */
struct {
ARMCondCode cond;
ARMBranchDest dest;
ARMBranchDest dest;
} BranchL; // -- don't want to do conditional BLs
-
+ /* Literal */
struct {
HReg reg;
ARMImm12A imm12a;
extern void ppARMInstr ( ARMInstr* );
-
-#if 0
/* Some functions that insulate the register allocator from details
of the underlying instruction set. */
+extern void getAllocableRegs_ARM ( Int*, HReg** );
extern void getRegUsage_ARMInstr ( HRegUsage*, ARMInstr* );
extern void mapRegs_ARMInstr ( HRegRemap*, ARMInstr* );
extern Bool isMove_ARMInstr ( ARMInstr*, HReg*, HReg* );
extern ARMInstr* genReload_ARM ( HReg rreg, Int offset );
extern void getAllocableRegs_ARM ( Int*, HReg** );
extern HInstrArray* iselBB_ARM ( IRBB* );
-#endif
#endif /* ndef __LIBVEX_ARMH_DEFS_H */