1bf215546Sopenharmony_ci/* -*- mesa-c++  -*-
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright (c) 2019 Collabora LTD
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Author: Gert Wollny <gert.wollny@collabora.com>
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
10bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
11bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
12bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
15bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
16bf215546Sopenharmony_ci * Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "sfn_conditionaljumptracker.h"
28bf215546Sopenharmony_ci#include "sfn_debug.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include <stack>
31bf215546Sopenharmony_ci#include <vector>
32bf215546Sopenharmony_ci#include <memory>
33bf215546Sopenharmony_ci#include <iostream>
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cinamespace r600 {
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ciusing std::stack;
38bf215546Sopenharmony_ciusing std::vector;
39bf215546Sopenharmony_ciusing std::shared_ptr;
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_cistruct StackFrame {
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   StackFrame(r600_bytecode_cf *s, JumpType t):
44bf215546Sopenharmony_ci      type(t),
45bf215546Sopenharmony_ci      start(s)
46bf215546Sopenharmony_ci   {}
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   virtual ~StackFrame();
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   JumpType type;
51bf215546Sopenharmony_ci   r600_bytecode_cf *start;
52bf215546Sopenharmony_ci   vector<r600_bytecode_cf *> mid;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   virtual void fixup_mid(r600_bytecode_cf *cf) = 0;
55bf215546Sopenharmony_ci   virtual void fixup_pop(r600_bytecode_cf *final) = 0;
56bf215546Sopenharmony_ci};
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ciusing PStackFrame = shared_ptr<StackFrame>;
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistruct IfFrame : public StackFrame {
61bf215546Sopenharmony_ci   IfFrame(r600_bytecode_cf *s);
62bf215546Sopenharmony_ci   void fixup_mid(r600_bytecode_cf *cf) override;
63bf215546Sopenharmony_ci   void fixup_pop(r600_bytecode_cf *final) override;
64bf215546Sopenharmony_ci};
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistruct LoopFrame : public StackFrame {
67bf215546Sopenharmony_ci   LoopFrame(r600_bytecode_cf *s);
68bf215546Sopenharmony_ci   void fixup_mid(r600_bytecode_cf *cf) override;
69bf215546Sopenharmony_ci   void fixup_pop(r600_bytecode_cf *final) override;
70bf215546Sopenharmony_ci};
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_cistruct ConditionalJumpTrackerImpl {
73bf215546Sopenharmony_ci   ConditionalJumpTrackerImpl();
74bf215546Sopenharmony_ci   stack<PStackFrame> m_jump_stack;
75bf215546Sopenharmony_ci   stack<PStackFrame> m_loop_stack;
76bf215546Sopenharmony_ci   int m_current_loop_stack_pos;
77bf215546Sopenharmony_ci};
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ciConditionalJumpTrackerImpl::ConditionalJumpTrackerImpl():
80bf215546Sopenharmony_ci   m_current_loop_stack_pos(0)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci}
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ciConditionalJumpTracker::~ConditionalJumpTracker()
86bf215546Sopenharmony_ci{
87bf215546Sopenharmony_ci   delete impl;
88bf215546Sopenharmony_ci}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ciConditionalJumpTracker::ConditionalJumpTracker()
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   impl = new ConditionalJumpTrackerImpl();
93bf215546Sopenharmony_ci}
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_civoid ConditionalJumpTracker::push(r600_bytecode_cf *start, JumpType type)
96bf215546Sopenharmony_ci{
97bf215546Sopenharmony_ci   PStackFrame f;
98bf215546Sopenharmony_ci   switch (type) {
99bf215546Sopenharmony_ci   case  jt_if:
100bf215546Sopenharmony_ci      f.reset(new IfFrame(start));
101bf215546Sopenharmony_ci      break;
102bf215546Sopenharmony_ci   case  jt_loop:
103bf215546Sopenharmony_ci      f.reset(new LoopFrame(start));
104bf215546Sopenharmony_ci      impl->m_loop_stack.push(f);
105bf215546Sopenharmony_ci      break;
106bf215546Sopenharmony_ci   }
107bf215546Sopenharmony_ci   impl->m_jump_stack.push(f);
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_cibool ConditionalJumpTracker::pop(r600_bytecode_cf *final, JumpType type)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   if (impl->m_jump_stack.empty())
113bf215546Sopenharmony_ci      return false;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   auto& frame = *impl->m_jump_stack.top();
116bf215546Sopenharmony_ci   if (frame.type != type)
117bf215546Sopenharmony_ci      return false;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   frame.fixup_pop(final);
120bf215546Sopenharmony_ci   if (frame.type == jt_loop)
121bf215546Sopenharmony_ci      impl->m_loop_stack.pop();
122bf215546Sopenharmony_ci   impl->m_jump_stack.pop();
123bf215546Sopenharmony_ci   return true;
124bf215546Sopenharmony_ci}
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cibool ConditionalJumpTracker::add_mid(r600_bytecode_cf *source, JumpType type)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   if (impl->m_jump_stack.empty()) {
129bf215546Sopenharmony_ci      sfn_log << "Jump stack empty\n";
130bf215546Sopenharmony_ci      return false;
131bf215546Sopenharmony_ci   }
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   PStackFrame pframe;
134bf215546Sopenharmony_ci   if (type == jt_loop) {
135bf215546Sopenharmony_ci      if (impl->m_loop_stack.empty()) {
136bf215546Sopenharmony_ci         sfn_log << "Loop jump stack empty\n";
137bf215546Sopenharmony_ci         return false;
138bf215546Sopenharmony_ci      }
139bf215546Sopenharmony_ci      pframe = impl->m_loop_stack.top();
140bf215546Sopenharmony_ci   } else {
141bf215546Sopenharmony_ci      pframe = impl->m_jump_stack.top();
142bf215546Sopenharmony_ci   }
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   pframe->mid.push_back(source);
145bf215546Sopenharmony_ci   pframe->fixup_mid(source);
146bf215546Sopenharmony_ci   return true;
147bf215546Sopenharmony_ci}
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ciIfFrame::IfFrame(r600_bytecode_cf *s):
150bf215546Sopenharmony_ci   StackFrame (s, jt_if)
151bf215546Sopenharmony_ci{
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ciStackFrame::~StackFrame()
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci}
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_civoid IfFrame::fixup_mid(r600_bytecode_cf *source)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   /* JUMP target is ELSE */
161bf215546Sopenharmony_ci   start->cf_addr = source->id;
162bf215546Sopenharmony_ci}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_civoid IfFrame::fixup_pop(r600_bytecode_cf *final)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   /* JUMP or ELSE target is one past last CF instruction */
167bf215546Sopenharmony_ci   unsigned offset = final->eg_alu_extended ? 4 : 2;
168bf215546Sopenharmony_ci   auto src = mid.empty() ? start : mid[0];
169bf215546Sopenharmony_ci   src->cf_addr = final->id + offset;
170bf215546Sopenharmony_ci   src->pop_count = 1;
171bf215546Sopenharmony_ci}
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ciLoopFrame::LoopFrame(r600_bytecode_cf *s):
174bf215546Sopenharmony_ci   StackFrame(s, jt_loop)
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_civoid LoopFrame::fixup_mid(UNUSED r600_bytecode_cf *mid)
179bf215546Sopenharmony_ci{
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_civoid LoopFrame::fixup_pop(r600_bytecode_cf *final)
183bf215546Sopenharmony_ci{
184bf215546Sopenharmony_ci   /* LOOP END address is past LOOP START */
185bf215546Sopenharmony_ci   final->cf_addr = start->id + 2;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   /* LOOP START address is past LOOP END*/
188bf215546Sopenharmony_ci   start->cf_addr = final->id + 2;
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   /* BREAK and CONTINUE point at LOOP END*/
191bf215546Sopenharmony_ci   for (auto m : mid)
192bf215546Sopenharmony_ci      m->cf_addr = final->id;
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci}
196