branch.isa revision 6691
16691Stjones1@inf.ed.ac.uk// -*- mode:c++ -*- 26691Stjones1@inf.ed.ac.uk 36691Stjones1@inf.ed.ac.uk// Copyright (c) 2009 The University of Edinburgh 46691Stjones1@inf.ed.ac.uk// All rights reserved. 56691Stjones1@inf.ed.ac.uk// 66691Stjones1@inf.ed.ac.uk// Redistribution and use in source and binary forms, with or without 76691Stjones1@inf.ed.ac.uk// modification, are permitted provided that the following conditions are 86691Stjones1@inf.ed.ac.uk// met: redistributions of source code must retain the above copyright 96691Stjones1@inf.ed.ac.uk// notice, this list of conditions and the following disclaimer; 106691Stjones1@inf.ed.ac.uk// redistributions in binary form must reproduce the above copyright 116691Stjones1@inf.ed.ac.uk// notice, this list of conditions and the following disclaimer in the 126691Stjones1@inf.ed.ac.uk// documentation and/or other materials provided with the distribution; 136691Stjones1@inf.ed.ac.uk// neither the name of the copyright holders nor the names of its 146691Stjones1@inf.ed.ac.uk// contributors may be used to endorse or promote products derived from 156691Stjones1@inf.ed.ac.uk// this software without specific prior written permission. 166691Stjones1@inf.ed.ac.uk// 176691Stjones1@inf.ed.ac.uk// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186691Stjones1@inf.ed.ac.uk// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196691Stjones1@inf.ed.ac.uk// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206691Stjones1@inf.ed.ac.uk// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216691Stjones1@inf.ed.ac.uk// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226691Stjones1@inf.ed.ac.uk// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236691Stjones1@inf.ed.ac.uk// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246691Stjones1@inf.ed.ac.uk// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256691Stjones1@inf.ed.ac.uk// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266691Stjones1@inf.ed.ac.uk// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276691Stjones1@inf.ed.ac.uk// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286691Stjones1@inf.ed.ac.uk// 296691Stjones1@inf.ed.ac.uk// Authors: Timothy M. Jones 306691Stjones1@inf.ed.ac.uk 316691Stjones1@inf.ed.ac.uk//////////////////////////////////////////////////////////////////// 326691Stjones1@inf.ed.ac.uk// 336691Stjones1@inf.ed.ac.uk// Control transfer instructions 346691Stjones1@inf.ed.ac.uk// 356691Stjones1@inf.ed.ac.uk// From the Power ISA Book I v2.06, page 33, the following rules should 366691Stjones1@inf.ed.ac.uk// be obeyed by programmers: 376691Stjones1@inf.ed.ac.uk// 386691Stjones1@inf.ed.ac.uk// - Use branch instructions where LK == 1 only as subroutine calls. 396691Stjones1@inf.ed.ac.uk// - Pair each subroutine call with a bclr instruction with BH == 00 406691Stjones1@inf.ed.ac.uk// that returns from the subroutine. 416691Stjones1@inf.ed.ac.uk// - Do not use bclrl as a subroutine call. 426691Stjones1@inf.ed.ac.uk// 436691Stjones1@inf.ed.ac.uk// Therefore, I've flagged all versions that update the link register (LR) 446691Stjones1@inf.ed.ac.uk// as calls, except bclrl (BranchLrCtrCond format) which is flagged as 456691Stjones1@inf.ed.ac.uk// a return. 466691Stjones1@inf.ed.ac.uk 476691Stjones1@inf.ed.ac.uk 486691Stjones1@inf.ed.ac.uklet {{ 496691Stjones1@inf.ed.ac.uk 506691Stjones1@inf.ed.ac.uk# Simple code to update link register (LR). 516691Stjones1@inf.ed.ac.ukupdateLrCode = 'LR = PC + 4;' 526691Stjones1@inf.ed.ac.uk 536691Stjones1@inf.ed.ac.uk}}; 546691Stjones1@inf.ed.ac.uk 556691Stjones1@inf.ed.ac.uk// Instructions that unconditionally branch relative to the current PC. 566691Stjones1@inf.ed.ac.ukdef format BranchPCRel(br_code, inst_flags = []) {{ 576691Stjones1@inf.ed.ac.uk inst_flags += ('IsUncondControl', 'IsDirectControl') 586691Stjones1@inf.ed.ac.uk basic_code = br_code 596691Stjones1@inf.ed.ac.uk 606691Stjones1@inf.ed.ac.uk # The version that does not update LR 616691Stjones1@inf.ed.ac.uk (header_output, decoder_output, decode_block, exec_output) = \ 626691Stjones1@inf.ed.ac.uk GenAluOp(name, Name, 'BranchPCRel', basic_code, inst_flags, 636691Stjones1@inf.ed.ac.uk CheckLkDecode, BasicConstructor) 646691Stjones1@inf.ed.ac.uk 656691Stjones1@inf.ed.ac.uk # The version that does the update 666691Stjones1@inf.ed.ac.uk update_code = basic_code + updateLrCode 676691Stjones1@inf.ed.ac.uk update_flags = inst_flags + [ 'IsCall' ] 686691Stjones1@inf.ed.ac.uk (header_output_up, decoder_output_up, _, exec_output_up) = \ 696691Stjones1@inf.ed.ac.uk GenAluOp(name, Name + 'UpdateLr', 'BranchPCRel', update_code, 706691Stjones1@inf.ed.ac.uk update_flags, CheckLkDecode, BasicConstructor) 716691Stjones1@inf.ed.ac.uk 726691Stjones1@inf.ed.ac.uk # Add the outputs together 736691Stjones1@inf.ed.ac.uk header_output += header_output_up 746691Stjones1@inf.ed.ac.uk decoder_output += decoder_output_up 756691Stjones1@inf.ed.ac.uk exec_output += exec_output_up 766691Stjones1@inf.ed.ac.uk}}; 776691Stjones1@inf.ed.ac.uk 786691Stjones1@inf.ed.ac.uk// Instructions that unconditionally branch to a specific address. 796691Stjones1@inf.ed.ac.ukdef format BranchNonPCRel(br_code, inst_flags = []) {{ 806691Stjones1@inf.ed.ac.uk inst_flags += ('IsUncondControl', 'IsDirectControl') 816691Stjones1@inf.ed.ac.uk basic_code = br_code 826691Stjones1@inf.ed.ac.uk 836691Stjones1@inf.ed.ac.uk # The version that does not update LR 846691Stjones1@inf.ed.ac.uk (header_output, decoder_output, decode_block, exec_output) = \ 856691Stjones1@inf.ed.ac.uk GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags, 866691Stjones1@inf.ed.ac.uk CheckLkDecode, BasicConstructor) 876691Stjones1@inf.ed.ac.uk 886691Stjones1@inf.ed.ac.uk # The version that does the update 896691Stjones1@inf.ed.ac.uk update_code = basic_code + updateLrCode 906691Stjones1@inf.ed.ac.uk update_flags = inst_flags + [ 'IsCall' ] 916691Stjones1@inf.ed.ac.uk (header_output_up, decoder_output_up, _, exec_output_up) = \ 926691Stjones1@inf.ed.ac.uk GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRel', update_code, 936691Stjones1@inf.ed.ac.uk update_flags, CheckLkDecode, BasicConstructor) 946691Stjones1@inf.ed.ac.uk 956691Stjones1@inf.ed.ac.uk # Add the outputs together 966691Stjones1@inf.ed.ac.uk header_output += header_output_up 976691Stjones1@inf.ed.ac.uk decoder_output += decoder_output_up 986691Stjones1@inf.ed.ac.uk exec_output += exec_output_up 996691Stjones1@inf.ed.ac.uk}}; 1006691Stjones1@inf.ed.ac.uk 1016691Stjones1@inf.ed.ac.uklet {{ 1026691Stjones1@inf.ed.ac.uk 1036691Stjones1@inf.ed.ac.uk# Check the condition register (CR) allows the branch to be taken. 1046691Stjones1@inf.ed.ac.ukdef GetCondCode(br_code): 1056691Stjones1@inf.ed.ac.uk cond_code = 'if(condOk(CR)) {\n' 1066691Stjones1@inf.ed.ac.uk cond_code += ' ' + br_code + '\n' 1076691Stjones1@inf.ed.ac.uk cond_code += '} else {\n' 1086691Stjones1@inf.ed.ac.uk cond_code += ' NPC = NPC;\n' 1096691Stjones1@inf.ed.ac.uk cond_code += '}\n' 1106691Stjones1@inf.ed.ac.uk return cond_code 1116691Stjones1@inf.ed.ac.uk 1126691Stjones1@inf.ed.ac.uk# Check the condition register (CR) and count register (CTR) allow the 1136691Stjones1@inf.ed.ac.uk# branch to be taken. Also, in certain situations, decrement the count 1146691Stjones1@inf.ed.ac.uk# register too. This takes place in ctrOk within BranchCond classes. 1156691Stjones1@inf.ed.ac.ukdef GetCtrCondCode(br_code): 1166691Stjones1@inf.ed.ac.uk cond_code = 'uint32_t ctr = CTR;\n' 1176691Stjones1@inf.ed.ac.uk cond_code += 'bool ctr_ok = ctrOk(ctr);\n' 1186691Stjones1@inf.ed.ac.uk cond_code += 'bool cond_ok = condOk(CR);\n' 1196691Stjones1@inf.ed.ac.uk cond_code += 'if(ctr_ok && cond_ok) {\n' 1206691Stjones1@inf.ed.ac.uk cond_code += ' ' + br_code + '\n' 1216691Stjones1@inf.ed.ac.uk cond_code += '} else {\n' 1226691Stjones1@inf.ed.ac.uk cond_code += ' NPC = NPC;\n' 1236691Stjones1@inf.ed.ac.uk cond_code += '}\n' 1246691Stjones1@inf.ed.ac.uk cond_code += 'CTR = ctr;\n' 1256691Stjones1@inf.ed.ac.uk return cond_code 1266691Stjones1@inf.ed.ac.uk 1276691Stjones1@inf.ed.ac.uk}}; 1286691Stjones1@inf.ed.ac.uk 1296691Stjones1@inf.ed.ac.uk// Instructions that conditionally branch relative to the current PC based on 1306691Stjones1@inf.ed.ac.uk// the condition register (CR) and count register (CTR). 1316691Stjones1@inf.ed.ac.ukdef format BranchPCRelCondCtr(br_code, inst_flags = []) {{ 1326691Stjones1@inf.ed.ac.uk inst_flags += ('IsCondControl', 'IsDirectControl') 1336691Stjones1@inf.ed.ac.uk basic_code = GetCtrCondCode(br_code) 1346691Stjones1@inf.ed.ac.uk 1356691Stjones1@inf.ed.ac.uk # The version that does not update LR 1366691Stjones1@inf.ed.ac.uk (header_output, decoder_output, decode_block, exec_output) = \ 1376691Stjones1@inf.ed.ac.uk GenAluOp(name, Name, 'BranchPCRelCond', basic_code, inst_flags, 1386691Stjones1@inf.ed.ac.uk CheckLkDecode, BasicConstructor) 1396691Stjones1@inf.ed.ac.uk 1406691Stjones1@inf.ed.ac.uk # The version that does the update 1416691Stjones1@inf.ed.ac.uk update_code = basic_code + updateLrCode 1426691Stjones1@inf.ed.ac.uk update_flags = inst_flags + [ 'IsCall' ] 1436691Stjones1@inf.ed.ac.uk (header_output_up, decoder_output_up, _, exec_output_up) = \ 1446691Stjones1@inf.ed.ac.uk GenAluOp(name, Name + 'UpdateLr', 'BranchPCRelCond', update_code, 1456691Stjones1@inf.ed.ac.uk update_flags, CheckLkDecode, BasicConstructor) 1466691Stjones1@inf.ed.ac.uk 1476691Stjones1@inf.ed.ac.uk # Add the outputs together 1486691Stjones1@inf.ed.ac.uk header_output += header_output_up 1496691Stjones1@inf.ed.ac.uk decoder_output += decoder_output_up 1506691Stjones1@inf.ed.ac.uk exec_output += exec_output_up 1516691Stjones1@inf.ed.ac.uk}}; 1526691Stjones1@inf.ed.ac.uk 1536691Stjones1@inf.ed.ac.uk// Instructions that conditionally branch to a specific address based on the 1546691Stjones1@inf.ed.ac.uk// condition register (CR) and count register (CTR). 1556691Stjones1@inf.ed.ac.ukdef format BranchNonPCRelCondCtr(br_code, inst_flags = []) {{ 1566691Stjones1@inf.ed.ac.uk inst_flags += ('IsCondControl', 'IsDirectControl') 1576691Stjones1@inf.ed.ac.uk basic_code = GetCtrCondCode(br_code) 1586691Stjones1@inf.ed.ac.uk 1596691Stjones1@inf.ed.ac.uk # The version that does not update LR 1606691Stjones1@inf.ed.ac.uk (header_output, decoder_output, decode_block, exec_output) = \ 1616691Stjones1@inf.ed.ac.uk GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags, 1626691Stjones1@inf.ed.ac.uk CheckLkDecode, BasicConstructor) 1636691Stjones1@inf.ed.ac.uk 1646691Stjones1@inf.ed.ac.uk # The version that does the update 1656691Stjones1@inf.ed.ac.uk update_code = basic_code + updateLrCode 1666691Stjones1@inf.ed.ac.uk update_flags = inst_flags + [ 'IsCall' ] 1676691Stjones1@inf.ed.ac.uk (header_output_up, decoder_output_up, _, exec_output_up) = \ 1686691Stjones1@inf.ed.ac.uk GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRelCond', update_code, 1696691Stjones1@inf.ed.ac.uk update_flags, CheckLkDecode, BasicConstructor) 1706691Stjones1@inf.ed.ac.uk 1716691Stjones1@inf.ed.ac.uk # Add the outputs together 1726691Stjones1@inf.ed.ac.uk header_output += header_output_up 1736691Stjones1@inf.ed.ac.uk decoder_output += decoder_output_up 1746691Stjones1@inf.ed.ac.uk exec_output += exec_output_up 1756691Stjones1@inf.ed.ac.uk}}; 1766691Stjones1@inf.ed.ac.uk 1776691Stjones1@inf.ed.ac.uk// Instructions that conditionally branch to the address in the link register 1786691Stjones1@inf.ed.ac.uk// (LR) based on the condition register (CR) and count register (CTR). 1796691Stjones1@inf.ed.ac.ukdef format BranchLrCondCtr(br_code, inst_flags = []) {{ 1806691Stjones1@inf.ed.ac.uk inst_flags += ('IsCondControl', 'IsIndirectControl', 'IsReturn') 1816691Stjones1@inf.ed.ac.uk basic_code = GetCtrCondCode(br_code) 1826691Stjones1@inf.ed.ac.uk 1836691Stjones1@inf.ed.ac.uk # The version that does not update LR 1846691Stjones1@inf.ed.ac.uk (header_output, decoder_output, decode_block, exec_output) = \ 1856691Stjones1@inf.ed.ac.uk GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, 1866691Stjones1@inf.ed.ac.uk CheckLkDecode, BasicConstructor) 1876691Stjones1@inf.ed.ac.uk 1886691Stjones1@inf.ed.ac.uk # The version that does the update 1896691Stjones1@inf.ed.ac.uk update_code = basic_code + updateLrCode 1906691Stjones1@inf.ed.ac.uk (header_output_up, decoder_output_up, _, exec_output_up) = \ 1916691Stjones1@inf.ed.ac.uk GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, 1926691Stjones1@inf.ed.ac.uk inst_flags, CheckLkDecode, BasicConstructor) 1936691Stjones1@inf.ed.ac.uk 1946691Stjones1@inf.ed.ac.uk # Add the outputs together 1956691Stjones1@inf.ed.ac.uk header_output += header_output_up 1966691Stjones1@inf.ed.ac.uk decoder_output += decoder_output_up 1976691Stjones1@inf.ed.ac.uk exec_output += exec_output_up 1986691Stjones1@inf.ed.ac.uk}}; 1996691Stjones1@inf.ed.ac.uk 2006691Stjones1@inf.ed.ac.uk// Instructions that conditionally branch to the address in the count register 2016691Stjones1@inf.ed.ac.uk// (CTR) based on the condition register (CR). 2026691Stjones1@inf.ed.ac.ukdef format BranchCtrCond(br_code, inst_flags = []) {{ 2036691Stjones1@inf.ed.ac.uk inst_flags += ('IsCondControl', 'IsIndirectControl') 2046691Stjones1@inf.ed.ac.uk basic_code = GetCondCode(br_code) 2056691Stjones1@inf.ed.ac.uk 2066691Stjones1@inf.ed.ac.uk # The version that does not update LR 2076691Stjones1@inf.ed.ac.uk (header_output, decoder_output, decode_block, exec_output) = \ 2086691Stjones1@inf.ed.ac.uk GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, 2096691Stjones1@inf.ed.ac.uk CheckLkDecode, BasicConstructor) 2106691Stjones1@inf.ed.ac.uk 2116691Stjones1@inf.ed.ac.uk # The version that does the update 2126691Stjones1@inf.ed.ac.uk update_code = basic_code + updateLrCode 2136691Stjones1@inf.ed.ac.uk update_flags = inst_flags + [ 'IsCall' ] 2146691Stjones1@inf.ed.ac.uk (header_output_up, decoder_output_up, _, exec_output_up) = \ 2156691Stjones1@inf.ed.ac.uk GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, 2166691Stjones1@inf.ed.ac.uk update_flags, CheckLkDecode, BasicConstructor) 2176691Stjones1@inf.ed.ac.uk 2186691Stjones1@inf.ed.ac.uk # Add the outputs together 2196691Stjones1@inf.ed.ac.uk header_output += header_output_up 2206691Stjones1@inf.ed.ac.uk decoder_output += decoder_output_up 2216691Stjones1@inf.ed.ac.uk exec_output += exec_output_up 2226691Stjones1@inf.ed.ac.uk}}; 223