3 * Copyright (c) 2019 Collabora LTD
5 * Author: Gert Wollny <gert.wollny@collabora.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "sfn_conditionaljumptracker.h"
28 #include "sfn_debug.h"
39 using std::shared_ptr
;
43 StackFrame(r600_bytecode_cf
*s
, JumpType t
):
48 virtual ~StackFrame();
51 r600_bytecode_cf
*start
;
52 vector
<r600_bytecode_cf
*> mid
;
54 virtual void fixup_mid(r600_bytecode_cf
*cf
) = 0;
55 virtual void fixup_pop(r600_bytecode_cf
*final
) = 0;
58 using PStackFrame
= shared_ptr
<StackFrame
>;
60 struct IfFrame
: public StackFrame
{
61 IfFrame(r600_bytecode_cf
*s
);
62 void fixup_mid(r600_bytecode_cf
*cf
) override
;
63 void fixup_pop(r600_bytecode_cf
*final
) override
;
66 struct LoopFrame
: public StackFrame
{
67 LoopFrame(r600_bytecode_cf
*s
);
68 void fixup_mid(r600_bytecode_cf
*cf
) override
;
69 void fixup_pop(r600_bytecode_cf
*final
) override
;
72 struct ConditionalJumpTrackerImpl
{
73 ConditionalJumpTrackerImpl();
74 stack
<PStackFrame
> m_jump_stack
;
75 stack
<PStackFrame
> m_loop_stack
;
76 int m_current_loop_stack_pos
;
79 ConditionalJumpTrackerImpl::ConditionalJumpTrackerImpl():
80 m_current_loop_stack_pos(0)
85 ConditionalJumpTracker::~ConditionalJumpTracker()
90 ConditionalJumpTracker::ConditionalJumpTracker()
92 impl
= new ConditionalJumpTrackerImpl();
95 void ConditionalJumpTracker::push(r600_bytecode_cf
*start
, JumpType type
)
100 f
.reset(new IfFrame(start
));
103 f
.reset(new LoopFrame(start
));
104 impl
->m_loop_stack
.push(f
);
107 impl
->m_jump_stack
.push(f
);
110 bool ConditionalJumpTracker::pop(r600_bytecode_cf
*final
, JumpType type
)
112 if (impl
->m_jump_stack
.empty())
115 auto& frame
= *impl
->m_jump_stack
.top();
116 if (frame
.type
!= type
)
119 frame
.fixup_pop(final
);
120 if (frame
.type
== jt_loop
)
121 impl
->m_loop_stack
.pop();
122 impl
->m_jump_stack
.pop();
126 bool ConditionalJumpTracker::add_mid(r600_bytecode_cf
*source
, JumpType type
)
128 if (impl
->m_jump_stack
.empty()) {
129 sfn_log
<< "Jump stack empty\n";
134 if (type
== jt_loop
) {
135 if (impl
->m_loop_stack
.empty()) {
136 sfn_log
<< "Loop jump stack empty\n";
139 pframe
= impl
->m_loop_stack
.top();
141 pframe
= impl
->m_jump_stack
.top();
144 pframe
->mid
.push_back(source
);
145 pframe
->fixup_mid(source
);
149 IfFrame::IfFrame(r600_bytecode_cf
*s
):
150 StackFrame (s
, jt_if
)
154 StackFrame::~StackFrame()
158 void IfFrame::fixup_mid(r600_bytecode_cf
*source
)
160 /* JUMP target is ELSE */
161 start
->cf_addr
= source
->id
;
164 void IfFrame::fixup_pop(r600_bytecode_cf
*final
)
166 /* JUMP or ELSE target is one past last CF instruction */
167 unsigned offset
= final
->eg_alu_extended
? 4 : 2;
168 auto src
= mid
.empty() ? start
: mid
[0];
169 src
->cf_addr
= final
->id
+ offset
;
173 LoopFrame::LoopFrame(r600_bytecode_cf
*s
):
174 StackFrame(s
, jt_loop
)
178 void LoopFrame::fixup_mid(UNUSED r600_bytecode_cf
*mid
)
182 void LoopFrame::fixup_pop(r600_bytecode_cf
*final
)
184 /* LOOP END addess is past LOOP START */
185 final
->cf_addr
= start
->id
+ 2;
187 /* LOOP START addess is past LOOP END*/
188 start
->cf_addr
= final
->id
+ 2;
190 /* BREAK amd CONINUE point at LOOP END*/
192 m
->cf_addr
= final
->id
;