1// -*- mode:c++ -*-
2
3// Copyright (c) 2009 The University of Edinburgh
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Timothy M. Jones
30
31////////////////////////////////////////////////////////////////////
32//
33// Control transfer instructions
34//
35// From the Power ISA Book I v2.06, page 33, the following rules should
36// be obeyed by programmers:
37//
38// - Use branch instructions where LK == 1 only as subroutine calls.
39// - Pair each subroutine call with a bclr instruction with BH == 00
40//   that returns from the subroutine.
41// - Do not use bclrl as a subroutine call.
42//
43// Therefore, I've flagged all versions that update the link register (LR)
44// as calls, except bclrl (BranchLrCtrCond format) which is flagged as
45// a return.
46
47
48let {{
49
50# Simple code to update link register (LR).
51updateLrCode = 'LR = CIA + 4;'
52
53}};
54
55// Instructions that unconditionally branch relative to the current PC.
56def format BranchPCRel(br_code, inst_flags = []) {{
57    inst_flags += ('IsUncondControl', 'IsDirectControl')
58    basic_code = br_code
59
60    # The version that does not update LR
61    (header_output, decoder_output, decode_block, exec_output) = \
62        GenAluOp(name, Name, 'BranchPCRel', basic_code, inst_flags,
63                 CheckLkDecode, BasicConstructor)
64
65    # The version that does the update
66    update_code = basic_code + updateLrCode
67    update_flags = inst_flags + [ 'IsCall' ]
68    (header_output_up, decoder_output_up, _, exec_output_up) = \
69        GenAluOp(name, Name + 'UpdateLr', 'BranchPCRel', update_code,
70                 update_flags, CheckLkDecode, BasicConstructor)
71
72    # Add the outputs together
73    header_output += header_output_up
74    decoder_output += decoder_output_up
75    exec_output += exec_output_up
76}};
77
78// Instructions that unconditionally branch to a specific address.
79def format BranchNonPCRel(br_code, inst_flags = []) {{
80    inst_flags += ('IsUncondControl', 'IsDirectControl')
81    basic_code = br_code
82
83    # The version that does not update LR
84    (header_output, decoder_output, decode_block, exec_output) = \
85        GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags,
86                 CheckLkDecode, BasicConstructor)
87
88    # The version that does the update
89    update_code = basic_code + updateLrCode
90    update_flags = inst_flags + [ 'IsCall' ]
91    (header_output_up, decoder_output_up, _, exec_output_up) = \
92        GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRel', update_code,
93                 update_flags, CheckLkDecode, BasicConstructor)
94
95    # Add the outputs together
96    header_output += header_output_up
97    decoder_output += decoder_output_up
98    exec_output += exec_output_up
99}};
100
101let {{
102
103# Check the condition register (CR) allows the branch to be taken.
104def GetCondCode(br_code):
105    cond_code =  'if(condOk(CR)) {\n'
106    cond_code += '    ' + br_code + '\n'
107    cond_code += '} else {\n'
108    cond_code += '    NIA = NIA;\n'
109    cond_code += '}\n'
110    return cond_code
111
112# Check the condition register (CR) and count register (CTR) allow the
113# branch to be taken. Also, in certain situations, decrement the count
114# register too. This takes place in ctrOk within BranchCond classes.
115def GetCtrCondCode(br_code):
116    cond_code =  'uint32_t ctr = CTR;\n'
117    cond_code += 'bool ctr_ok = ctrOk(ctr);\n'
118    cond_code += 'bool cond_ok = condOk(CR);\n'
119    cond_code += 'if(ctr_ok && cond_ok) {\n'
120    cond_code += '    ' + br_code + '\n'
121    cond_code += '} else {\n'
122    cond_code += '    NIA = NIA;\n'
123    cond_code += '}\n'
124    cond_code += 'CTR = ctr;\n'
125    return cond_code
126
127}};
128
129// Instructions that conditionally branch relative to the current PC based on
130// the condition register (CR) and count register (CTR).
131def format BranchPCRelCondCtr(br_code, inst_flags = []) {{
132    inst_flags += ('IsCondControl', 'IsDirectControl')
133    basic_code = GetCtrCondCode(br_code)
134
135    # The version that does not update LR
136    (header_output, decoder_output, decode_block, exec_output) = \
137        GenAluOp(name, Name, 'BranchPCRelCond', basic_code, inst_flags,
138                 CheckLkDecode, BasicConstructor)
139
140    # The version that does the update
141    update_code = basic_code + updateLrCode
142    update_flags = inst_flags + [ 'IsCall' ]
143    (header_output_up, decoder_output_up, _, exec_output_up) = \
144        GenAluOp(name, Name + 'UpdateLr', 'BranchPCRelCond', update_code,
145                 update_flags, CheckLkDecode, BasicConstructor)
146
147    # Add the outputs together
148    header_output += header_output_up
149    decoder_output += decoder_output_up
150    exec_output += exec_output_up
151}};
152
153// Instructions that conditionally branch to a specific address based on the
154// condition register (CR) and count register (CTR).
155def format BranchNonPCRelCondCtr(br_code, inst_flags = []) {{
156    inst_flags += ('IsCondControl', 'IsDirectControl')
157    basic_code = GetCtrCondCode(br_code)
158
159    # The version that does not update LR
160    (header_output, decoder_output, decode_block, exec_output) = \
161        GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags,
162                 CheckLkDecode, BasicConstructor)
163
164    # The version that does the update
165    update_code = basic_code + updateLrCode
166    update_flags = inst_flags + [ 'IsCall' ]
167    (header_output_up, decoder_output_up, _, exec_output_up) = \
168        GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRelCond', update_code,
169                 update_flags, CheckLkDecode, BasicConstructor)
170
171    # Add the outputs together
172    header_output += header_output_up
173    decoder_output += decoder_output_up
174    exec_output += exec_output_up
175}};
176
177// Instructions that conditionally branch to the address in the link register
178// (LR) based on the condition register (CR) and count register (CTR).
179def format BranchLrCondCtr(br_code, inst_flags = []) {{
180    inst_flags += ('IsCondControl', 'IsIndirectControl', 'IsReturn')
181    basic_code = GetCtrCondCode(br_code)
182
183    # The version that does not update LR
184    (header_output, decoder_output, decode_block, exec_output) = \
185        GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags,
186                 CheckLkDecode, BasicConstructor)
187
188    # The version that does the update
189    update_code = basic_code + updateLrCode
190    (header_output_up, decoder_output_up, _, exec_output_up) = \
191        GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code,
192                 inst_flags, CheckLkDecode, BasicConstructor)
193
194    # Add the outputs together
195    header_output += header_output_up
196    decoder_output += decoder_output_up
197    exec_output += exec_output_up
198}};
199
200// Instructions that conditionally branch to the address in the count register
201// (CTR) based on the condition register (CR).
202def format BranchCtrCond(br_code, inst_flags = []) {{
203    inst_flags += ('IsCondControl', 'IsIndirectControl')
204    basic_code = GetCondCode(br_code)
205
206    # The version that does not update LR
207    (header_output, decoder_output, decode_block, exec_output) = \
208        GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags,
209                 CheckLkDecode, BasicConstructor)
210
211    # The version that does the update
212    update_code = basic_code + updateLrCode
213    update_flags = inst_flags + [ 'IsCall' ]
214    (header_output_up, decoder_output_up, _, exec_output_up) = \
215        GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code,
216                 update_flags, CheckLkDecode, BasicConstructor)
217
218    # Add the outputs together
219    header_output += header_output_up
220    decoder_output += decoder_output_up
221    exec_output += exec_output_up
222}};
223