192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri/**************************************************************************
292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *
392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Copyright 2010 Luca Barbieri
492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *
592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * Permission is hereby granted, free of charge, to any person obtaining
692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * a copy of this software and associated documentation files (the
792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * "Software"), to deal in the Software without restriction, including
892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * without limitation the rights to use, copy, modify, merge, publish,
992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * distribute, sublicense, and/or sell copies of the Software, and to
1092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * permit persons to whom the Software is furnished to do so, subject to
1192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * the following conditions:
1292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *
1392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * The above copyright notice and this permission notice (including the
1492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * next paragraph) shall be included in all copies or substantial
1592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * portions of the Software.
1692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *
1792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
2192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri *
2592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri **************************************************************************/
2692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri
2792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <vector>
2892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#include <set>
29e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri#include "sm4.h"
3092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri
3192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri#define check(x) do {if(!(x)) return false;} while(0)
3292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri
33e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieribool sm4_link_cf_insns(sm4_program& program)
3492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{
3592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	if(program.cf_insn_linked.size())
3692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		return true;
3792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri
3892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	std::vector<int> cf_insn_linked;
391aed6f42e9da0ca85b4d204d9dcaaa4632b34230Luca Barbieri	cf_insn_linked.resize(program.insns.size());
4092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	memset(&cf_insn_linked[0], 0xff, cf_insn_linked.size() * sizeof(int));
4192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	std::vector<unsigned> cf_stack;
4292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num)
4392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	{
4492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		unsigned v;
4592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		switch(program.insns[insn_num]->opcode)
4692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		{
47e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_LOOP:
4892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_stack.push_back(insn_num);
4992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			break;
50e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_ENDLOOP:
5192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			check(!cf_stack.empty());
5292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			v = cf_stack.back();
53e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri			check(program.insns[v]->opcode == SM4_OPCODE_LOOP);
5492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[v] = insn_num;
5592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[insn_num] = v;
5692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_stack.pop_back();
5792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			break;
58e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_IF:
59e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_SWITCH:
6092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[insn_num] = insn_num; // later changed
6192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_stack.push_back(insn_num);
6292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			break;
63e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_ELSE:
64e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_CASE:
6592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			check(!cf_stack.empty());
6692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			v = cf_stack.back();
67e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri			if(program.insns[insn_num]->opcode == SM4_OPCODE_ELSE)
68e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri				check(program.insns[v]->opcode == SM4_OPCODE_IF);
6992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			else
70e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri				check(program.insns[v]->opcode == SM4_OPCODE_SWITCH || program.insns[v]->opcode == SM4_OPCODE_CASE);
7192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[insn_num] = cf_insn_linked[v]; // later changed
7292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[v] = insn_num;
7392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_stack.back() = insn_num;
7492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			break;
75e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_ENDSWITCH:
76e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_ENDIF:
7792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			check(!cf_stack.empty());
7892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			v = cf_stack.back();
79e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri			if(program.insns[insn_num]->opcode == SM4_OPCODE_ENDIF)
80e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri				check(program.insns[v]->opcode == SM4_OPCODE_IF || program.insns[v]->opcode == SM4_OPCODE_ELSE);
8192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			else
82e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri				check(program.insns[v]->opcode == SM4_OPCODE_SWITCH || program.insns[v]->opcode == SM4_OPCODE_CASE);
8392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[insn_num] = cf_insn_linked[v];
8492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_insn_linked[v] = insn_num;
8592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			cf_stack.pop_back();
8692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			break;
8792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		}
8892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	}
8992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	check(cf_stack.empty());
9092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	program.cf_insn_linked.swap(cf_insn_linked);
9192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	return true;
9292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}
9392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri
94e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieribool sm4_find_labels(sm4_program& program)
9592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri{
9692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	if(program.labels_found)
9792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		return true;
9892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri
9992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	std::vector<int> labels;
10092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	for(unsigned insn_num = 0; insn_num < program.insns.size(); ++insn_num)
10192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	{
10292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		switch(program.insns[insn_num]->opcode)
10392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		{
104e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri		case SM4_OPCODE_LABEL:
10592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			if(program.insns[insn_num]->num_ops > 0)
10692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			{
107e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri				sm4_op& op = *program.insns[insn_num]->ops[0];
108e5ae4588d150a179974a812887f3b6445d8e2f34Luca Barbieri				if(op.file == SM4_FILE_LABEL && op.has_simple_index())
10992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri				{
11092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri					unsigned idx = (unsigned)op.indices[0].disp;
11192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri					if(idx >= labels.size())
11292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri						labels.resize(idx + 1);
11392617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri					labels[idx] = insn_num;
11492617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri				}
11592617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			}
11692617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri			break;
11792617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri		}
11892617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	}
11992617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	program.label_to_insn_num.swap(labels);
12092617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	program.labels_found = true;
12192617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri	return true;
12292617aeac109481258f0c3863d09c1b8903d438bLuca Barbieri}
123