static_inst.cc revision 6254:8abc40611938
16691Stjones1@inf.ed.ac.uk/* Copyright (c) 2007-2008 The Florida State University 26691Stjones1@inf.ed.ac.uk * All rights reserved. 36691Stjones1@inf.ed.ac.uk * 46691Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without 56691Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are 66691Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright 76691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer; 86691Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright 96691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the 106691Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution; 116691Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its 126691Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from 136691Stjones1@inf.ed.ac.uk * this software without specific prior written permission. 146691Stjones1@inf.ed.ac.uk * 156691Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 166691Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 176691Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 186691Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 196691Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 206691Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 216691Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 226691Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 236691Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 246691Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 256691Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 266691Stjones1@inf.ed.ac.uk * 276691Stjones1@inf.ed.ac.uk * Authors: Stephen Hines 286691Stjones1@inf.ed.ac.uk */ 296691Stjones1@inf.ed.ac.uk 306691Stjones1@inf.ed.ac.uk#include "arch/arm/insts/static_inst.hh" 316691Stjones1@inf.ed.ac.uk 326691Stjones1@inf.ed.ac.uknamespace ArmISA 336691Stjones1@inf.ed.ac.uk{ 346691Stjones1@inf.ed.ac.ukstatic int32_t arm_NEG(int32_t val) { return (val >> 31); } 356691Stjones1@inf.ed.ac.ukstatic int32_t arm_POS(int32_t val) { return ((~val) >> 31); } 366691Stjones1@inf.ed.ac.uk 376691Stjones1@inf.ed.ac.uk// Shift Rm by an immediate value 386691Stjones1@inf.ed.ac.ukint32_t 396691Stjones1@inf.ed.ac.ukArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, 406691Stjones1@inf.ed.ac.uk uint32_t type, uint32_t cfval) const 416691Stjones1@inf.ed.ac.uk{ 426691Stjones1@inf.ed.ac.uk enum ArmShiftType shiftType; 436691Stjones1@inf.ed.ac.uk shiftType = (enum ArmShiftType) type; 446691Stjones1@inf.ed.ac.uk 456691Stjones1@inf.ed.ac.uk switch (shiftType) 466691Stjones1@inf.ed.ac.uk { 476691Stjones1@inf.ed.ac.uk case LSL: 486691Stjones1@inf.ed.ac.uk return (base << shamt); 496691Stjones1@inf.ed.ac.uk case LSR: 506691Stjones1@inf.ed.ac.uk if (shamt == 0) 516691Stjones1@inf.ed.ac.uk return (0); 526691Stjones1@inf.ed.ac.uk else 536691Stjones1@inf.ed.ac.uk return (base >> shamt); 546691Stjones1@inf.ed.ac.uk case ASR: 556691Stjones1@inf.ed.ac.uk if (shamt == 0) 566691Stjones1@inf.ed.ac.uk return ((uint32_t) ((int32_t) base >> 31L)); 576691Stjones1@inf.ed.ac.uk else 586691Stjones1@inf.ed.ac.uk return ((uint32_t) (((int32_t) base) >> shamt)); 596691Stjones1@inf.ed.ac.uk case ROR: 606691Stjones1@inf.ed.ac.uk //shamt = shamt & 0x1f; 616691Stjones1@inf.ed.ac.uk if (shamt == 0) 626691Stjones1@inf.ed.ac.uk return (cfval << 31) | (base >> 1); // RRX 636691Stjones1@inf.ed.ac.uk else 646691Stjones1@inf.ed.ac.uk return (base << (32 - shamt)) | (base >> shamt); 656691Stjones1@inf.ed.ac.uk default: 666691Stjones1@inf.ed.ac.uk fprintf(stderr, "Unhandled shift type\n"); 676691Stjones1@inf.ed.ac.uk exit(1); 686691Stjones1@inf.ed.ac.uk break; 696691Stjones1@inf.ed.ac.uk } 706691Stjones1@inf.ed.ac.uk return 0; 716691Stjones1@inf.ed.ac.uk} 726691Stjones1@inf.ed.ac.uk 736691Stjones1@inf.ed.ac.uk// Shift Rm by Rs 746691Stjones1@inf.ed.ac.ukint32_t 756691Stjones1@inf.ed.ac.ukArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, 766691Stjones1@inf.ed.ac.uk uint32_t type, uint32_t cfval) const 776691Stjones1@inf.ed.ac.uk{ 786691Stjones1@inf.ed.ac.uk enum ArmShiftType shiftType; 796691Stjones1@inf.ed.ac.uk shiftType = (enum ArmShiftType) type; 806691Stjones1@inf.ed.ac.uk 816691Stjones1@inf.ed.ac.uk switch (shiftType) 826691Stjones1@inf.ed.ac.uk { 836691Stjones1@inf.ed.ac.uk case LSL: 846691Stjones1@inf.ed.ac.uk if (shamt == 0) 856691Stjones1@inf.ed.ac.uk return (base); 866691Stjones1@inf.ed.ac.uk else if (shamt >= 32) 876691Stjones1@inf.ed.ac.uk return (0); 886691Stjones1@inf.ed.ac.uk else 896691Stjones1@inf.ed.ac.uk return (base << shamt); 906691Stjones1@inf.ed.ac.uk case LSR: 916691Stjones1@inf.ed.ac.uk if (shamt == 0) 926691Stjones1@inf.ed.ac.uk return (base); 936691Stjones1@inf.ed.ac.uk else if (shamt >= 32) 946691Stjones1@inf.ed.ac.uk return (0); 956691Stjones1@inf.ed.ac.uk else 966691Stjones1@inf.ed.ac.uk return (base >> shamt); 976691Stjones1@inf.ed.ac.uk case ASR: 986691Stjones1@inf.ed.ac.uk if (shamt == 0) 996691Stjones1@inf.ed.ac.uk return base; 1006691Stjones1@inf.ed.ac.uk else if (shamt >= 32) 1016691Stjones1@inf.ed.ac.uk return ((uint32_t) ((int32_t) base >> 31L)); 1026691Stjones1@inf.ed.ac.uk else 1036691Stjones1@inf.ed.ac.uk return ((uint32_t) (((int32_t) base) >> (int) shamt)); 1046691Stjones1@inf.ed.ac.uk case ROR: 1056691Stjones1@inf.ed.ac.uk shamt = shamt & 0x1f; 1066691Stjones1@inf.ed.ac.uk if (shamt == 0) 1076691Stjones1@inf.ed.ac.uk return (base); 1086691Stjones1@inf.ed.ac.uk else 1096691Stjones1@inf.ed.ac.uk return ((base << (32 - shamt)) | (base >> shamt)); 1106691Stjones1@inf.ed.ac.uk default: 1116691Stjones1@inf.ed.ac.uk fprintf(stderr, "Unhandled shift type\n"); 1126691Stjones1@inf.ed.ac.uk exit(1); 1136691Stjones1@inf.ed.ac.uk break; 1146691Stjones1@inf.ed.ac.uk } 1156691Stjones1@inf.ed.ac.uk return 0; 1166691Stjones1@inf.ed.ac.uk} 1176691Stjones1@inf.ed.ac.uk 1186691Stjones1@inf.ed.ac.uk 1196691Stjones1@inf.ed.ac.uk// Generate C for a shift by immediate 1206691Stjones1@inf.ed.ac.ukint32_t 1216691Stjones1@inf.ed.ac.ukArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, 1226691Stjones1@inf.ed.ac.uk uint32_t type, uint32_t cfval) const 1236691Stjones1@inf.ed.ac.uk{ 1246691Stjones1@inf.ed.ac.uk enum ArmShiftType shiftType; 1256691Stjones1@inf.ed.ac.uk shiftType = (enum ArmShiftType) type; 1266691Stjones1@inf.ed.ac.uk 1276691Stjones1@inf.ed.ac.uk switch (shiftType) 1286691Stjones1@inf.ed.ac.uk { 1296691Stjones1@inf.ed.ac.uk case LSL: 1306691Stjones1@inf.ed.ac.uk return (base >> (32 - shamt)) & 1; 1316691Stjones1@inf.ed.ac.uk case LSR: 1326691Stjones1@inf.ed.ac.uk if (shamt == 0) 1336691Stjones1@inf.ed.ac.uk return (base >> 31) & 1; 1346691Stjones1@inf.ed.ac.uk else 1356691Stjones1@inf.ed.ac.uk return (base >> (shamt - 1)) & 1; 1366691Stjones1@inf.ed.ac.uk case ASR: 1376691Stjones1@inf.ed.ac.uk if (shamt == 0) 1386691Stjones1@inf.ed.ac.uk return (base >> 31L); 1396691Stjones1@inf.ed.ac.uk else 1406691Stjones1@inf.ed.ac.uk return ((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1; 1416691Stjones1@inf.ed.ac.uk case ROR: 1426691Stjones1@inf.ed.ac.uk shamt = shamt & 0x1f; 1436691Stjones1@inf.ed.ac.uk if (shamt == 0) 1446691Stjones1@inf.ed.ac.uk return (base & 1); // RRX 1456691Stjones1@inf.ed.ac.uk else 1466691Stjones1@inf.ed.ac.uk return (base >> (shamt - 1)) & 1; 1476691Stjones1@inf.ed.ac.uk default: 1486691Stjones1@inf.ed.ac.uk fprintf(stderr, "Unhandled shift type\n"); 1496691Stjones1@inf.ed.ac.uk exit(1); 1506691Stjones1@inf.ed.ac.uk break; 1516691Stjones1@inf.ed.ac.uk 1526691Stjones1@inf.ed.ac.uk } 1536691Stjones1@inf.ed.ac.uk return 0; 1546691Stjones1@inf.ed.ac.uk} 1556691Stjones1@inf.ed.ac.uk 1566691Stjones1@inf.ed.ac.uk 1576691Stjones1@inf.ed.ac.uk// Generate C for a shift by Rs 1586691Stjones1@inf.ed.ac.ukint32_t 1596691Stjones1@inf.ed.ac.ukArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, 1606691Stjones1@inf.ed.ac.uk uint32_t type, uint32_t cfval) const 1616691Stjones1@inf.ed.ac.uk{ 1626691Stjones1@inf.ed.ac.uk enum ArmShiftType shiftType; 1636691Stjones1@inf.ed.ac.uk shiftType = (enum ArmShiftType) type; 1646691Stjones1@inf.ed.ac.uk 1656691Stjones1@inf.ed.ac.uk switch (shiftType) 1666691Stjones1@inf.ed.ac.uk { 1676691Stjones1@inf.ed.ac.uk case LSL: 1686691Stjones1@inf.ed.ac.uk if (shamt == 0) 1696691Stjones1@inf.ed.ac.uk return (!!cfval); 1706691Stjones1@inf.ed.ac.uk else if (shamt == 32) 1716691Stjones1@inf.ed.ac.uk return (base & 1); 1726691Stjones1@inf.ed.ac.uk else if (shamt > 32) 1736691Stjones1@inf.ed.ac.uk return (0); 1746691Stjones1@inf.ed.ac.uk else 1756691Stjones1@inf.ed.ac.uk return ((base >> (32 - shamt)) & 1); 1766691Stjones1@inf.ed.ac.uk case LSR: 1776691Stjones1@inf.ed.ac.uk if (shamt == 0) 1786691Stjones1@inf.ed.ac.uk return (!!cfval); 1796691Stjones1@inf.ed.ac.uk else if (shamt == 32) 1806691Stjones1@inf.ed.ac.uk return (base >> 31); 1816691Stjones1@inf.ed.ac.uk else if (shamt > 32) 1826691Stjones1@inf.ed.ac.uk return (0); 1836691Stjones1@inf.ed.ac.uk else 1846691Stjones1@inf.ed.ac.uk return ((base >> (shamt - 1)) & 1); 1856691Stjones1@inf.ed.ac.uk case ASR: 1866691Stjones1@inf.ed.ac.uk if (shamt == 0) 1876691Stjones1@inf.ed.ac.uk return (!!cfval); 1886691Stjones1@inf.ed.ac.uk else if (shamt >= 32) 1896691Stjones1@inf.ed.ac.uk return (base >> 31L); 1906691Stjones1@inf.ed.ac.uk else 1916691Stjones1@inf.ed.ac.uk return (((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1); 1926691Stjones1@inf.ed.ac.uk case ROR: 1936691Stjones1@inf.ed.ac.uk if (shamt == 0) 1946691Stjones1@inf.ed.ac.uk return (!!cfval); 1956691Stjones1@inf.ed.ac.uk shamt = shamt & 0x1f; 1966691Stjones1@inf.ed.ac.uk if (shamt == 0) 1976691Stjones1@inf.ed.ac.uk return (base >> 31); // RRX 1986691Stjones1@inf.ed.ac.uk else 1996691Stjones1@inf.ed.ac.uk return ((base >> (shamt - 1)) & 1); 2006691Stjones1@inf.ed.ac.uk default: 2016691Stjones1@inf.ed.ac.uk fprintf(stderr, "Unhandled shift type\n"); 2026691Stjones1@inf.ed.ac.uk exit(1); 2036691Stjones1@inf.ed.ac.uk break; 2046691Stjones1@inf.ed.ac.uk 2056691Stjones1@inf.ed.ac.uk } 2066691Stjones1@inf.ed.ac.uk return 0; 2076691Stjones1@inf.ed.ac.uk} 2086691Stjones1@inf.ed.ac.uk 2096691Stjones1@inf.ed.ac.uk 2106691Stjones1@inf.ed.ac.uk// Generate the appropriate carry bit for an addition operation 2116691Stjones1@inf.ed.ac.ukint32_t 2126691Stjones1@inf.ed.ac.ukArmStaticInst::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const 2136691Stjones1@inf.ed.ac.uk{ 2146691Stjones1@inf.ed.ac.uk if ((lhs | rhs) >> 30) 2156691Stjones1@inf.ed.ac.uk return ((arm_NEG(lhs) && arm_NEG(rhs)) || 2166691Stjones1@inf.ed.ac.uk (arm_NEG(lhs) && arm_POS(result)) || 2176691Stjones1@inf.ed.ac.uk (arm_NEG(rhs) && arm_POS(result))); 2186691Stjones1@inf.ed.ac.uk 2196691Stjones1@inf.ed.ac.uk return 0; 2206691Stjones1@inf.ed.ac.uk} 2216691Stjones1@inf.ed.ac.uk 2226691Stjones1@inf.ed.ac.uk// Generate the appropriate carry bit for a subtraction operation 2236691Stjones1@inf.ed.ac.ukint32_t 2246691Stjones1@inf.ed.ac.ukArmStaticInst::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const 2256691Stjones1@inf.ed.ac.uk{ 2266691Stjones1@inf.ed.ac.uk if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2276691Stjones1@inf.ed.ac.uk return ((arm_NEG(lhs) && arm_POS(rhs)) || 2286691Stjones1@inf.ed.ac.uk (arm_NEG(lhs) && arm_POS(result)) || 2296691Stjones1@inf.ed.ac.uk (arm_POS(rhs) && arm_POS(result))); 2306691Stjones1@inf.ed.ac.uk 2316691Stjones1@inf.ed.ac.uk return 0; 2326691Stjones1@inf.ed.ac.uk} 2336691Stjones1@inf.ed.ac.uk 2346691Stjones1@inf.ed.ac.ukint32_t 2356691Stjones1@inf.ed.ac.ukArmStaticInst::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const 2366691Stjones1@inf.ed.ac.uk{ 2376691Stjones1@inf.ed.ac.uk if ((lhs | rhs) >> 30) 2386691Stjones1@inf.ed.ac.uk return ((arm_NEG(lhs) && arm_NEG(rhs) && arm_POS(result)) || 2396691Stjones1@inf.ed.ac.uk (arm_POS(lhs) && arm_POS(rhs) && arm_NEG(result))); 2406691Stjones1@inf.ed.ac.uk 2416691Stjones1@inf.ed.ac.uk return 0; 2426691Stjones1@inf.ed.ac.uk} 2436691Stjones1@inf.ed.ac.uk 2446691Stjones1@inf.ed.ac.ukint32_t 2456691Stjones1@inf.ed.ac.ukArmStaticInst::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const 2466691Stjones1@inf.ed.ac.uk{ 2476691Stjones1@inf.ed.ac.uk if ((lhs >= rhs) || ((rhs | lhs) >> 31)) 2486691Stjones1@inf.ed.ac.uk return ((arm_NEG(lhs) && arm_POS(rhs) && arm_POS(result)) || 2496691Stjones1@inf.ed.ac.uk (arm_POS(lhs) && arm_NEG(rhs) && arm_NEG(result))); 2506691Stjones1@inf.ed.ac.uk 2516691Stjones1@inf.ed.ac.uk return 0; 2526691Stjones1@inf.ed.ac.uk} 2536691Stjones1@inf.ed.ac.uk 2546691Stjones1@inf.ed.ac.ukvoid 2556691Stjones1@inf.ed.ac.ukArmStaticInst::printReg(std::ostream &os, int reg) const 2566691Stjones1@inf.ed.ac.uk{ 2576691Stjones1@inf.ed.ac.uk if (reg < FP_Base_DepTag) { 2586691Stjones1@inf.ed.ac.uk ccprintf(os, "r%d", reg); 2596691Stjones1@inf.ed.ac.uk } 2606691Stjones1@inf.ed.ac.uk else { 2616691Stjones1@inf.ed.ac.uk ccprintf(os, "f%d", reg - FP_Base_DepTag); 2626691Stjones1@inf.ed.ac.uk } 2636691Stjones1@inf.ed.ac.uk} 2646691Stjones1@inf.ed.ac.uk 2656691Stjones1@inf.ed.ac.ukstd::string 2666691Stjones1@inf.ed.ac.ukArmStaticInst::generateDisassembly(Addr pc, 2676691Stjones1@inf.ed.ac.uk const SymbolTable *symtab) const 2686691Stjones1@inf.ed.ac.uk{ 2696701Sgblack@eecs.umich.edu std::stringstream ss; 2706691Stjones1@inf.ed.ac.uk 2716691Stjones1@inf.ed.ac.uk ccprintf(ss, "%-10s ", mnemonic); 2726701Sgblack@eecs.umich.edu 2736691Stjones1@inf.ed.ac.uk return ss.str(); 2746691Stjones1@inf.ed.ac.uk} 2756691Stjones1@inf.ed.ac.uk} 2766691Stjones1@inf.ed.ac.uk