Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <mach.h>
5
#define Extern extern
6
#include "power.h"
7
 
8
void	mcrf(ulong);
9
void	bclr(ulong);
10
void	crop(ulong);
11
void	bcctr(ulong);
12
void	call(ulong);
13
void	ret(ulong);
14
void isync(ulong);
15
 
16
Inst	op19[] = {
17
[0] {mcrf, "mcrf", Ibranch},
18
[16] {bclr, "bclr", Ibranch},
19
[33] {crop, "crnor", Ibranch},
20
[15] {0, "rfi", Ibranch},
21
[129] {crop, "crandc", Ibranch},
22
[150] {isync, "isync", Ibranch},
23
[193] {crop, "crxor", Ibranch},
24
[225] {crop, "crnand", Ibranch},
25
[257] {crop, "crand", Ibranch},
26
[289] {crop, "creqv", Ibranch},
27
[417] {crop, "crorc", Ibranch},
28
[449] {crop, "cror", Ibranch},
29
[528] {bcctr, "bcctr", Ibranch},
30
	{0, 0, 0}
31
};
32
 
33
Inset	ops19 = {op19, nelem(op19)-1};
34
 
35
static char *
36
boname(int bo)
37
{
38
	static char buf[8];
39
 
40
	switch(bo>>1){
41
	case 0:	return "dnzf";
42
	case 1:	return "dzf";
43
	case 2:	return "f";
44
	case 4:	return "dnzt";
45
	case 5:	return "dzt";
46
	case 6:	return "t";
47
	case 8:	return "dnz";
48
	case 9:	return "dz";
49
	case 10:	return "a";
50
	default:
51
		sprint(buf, "%d?", bo);
52
		return buf;
53
	}
54
}
55
 
56
static char *
57
cname(int bo, int bi)
58
{
59
	int f;
60
	char *p;
61
	static char buf[20];
62
	static char *f0[] = {"lt", "gt", "eq", "so/un"};
63
 
64
	if(bo == 0x14){	/* branch always */
65
		sprint(buf,"%d", bi);
66
		return buf;
67
	}
68
	for(f = 0; bi >= 4; bi -= 4)
69
		f++;
70
	p = buf;
71
	p += sprint(buf, "%d[", bi);
72
	if(f)
73
		p += sprint(buf, "cr%d+", f);
74
	strcpy(p, f0[bi&3]);
75
	strcat(p, "]");
76
	return buf;
77
}
78
 
79
static int
80
condok(ulong ir, int ctr)
81
{
82
	int bo, bi, xx;
83
 
84
	getbobi(ir);
85
	if(xx)
86
		undef(ir);
87
	if((bo & 0x4) == 0) {
88
		if(!ctr)
89
			undef(ir);
90
		reg.ctr--;
91
	}
92
	if(bo & 0x4 || (reg.ctr!=0)^((bo>>1)&1)) {
93
		if(bo & 0x10 || (((reg.cr & bits[bi])!=0)==((bo>>3)&1)))
94
			return 1;
95
	}
96
	return 0;
97
}
98
 
99
static void
100
dobranch(ulong ir, ulong *r, int ctr)
101
{
102
	int bo, bi, xx;
103
	ulong nia;
104
 
105
	getbobi(ir);
106
	USED(xx);
107
	if(condok(ir, ctr)) {
108
		ci->taken++;
109
		nia = *r & ~3;
110
		if(bo & 4)	/* assume counting branches aren't returns */
111
			ret(nia);
112
	} else
113
		nia = reg.pc + 4;
114
	if(trace)
115
		itrace("%s%s\t%s,%s,#%.8lux", ci->name, ir&1? "l": "", boname(bo), cname(bo, bi), nia);
116
	if(ir & 1) {
117
		call(nia);
118
		reg.lr = reg.pc + 4;
119
	}
120
	reg.pc = nia-4;
121
	/* branch delays? */
122
}
123
 
124
void
125
bcctr(ulong ir)
126
{
127
	dobranch(ir, &reg.ctr, 1);
128
}
129
 
130
void
131
bclr(ulong ir)
132
{
133
	dobranch(ir, &reg.lr, 0);
134
}
135
 
136
void
137
bcx(ulong ir)
138
{
139
	int bo, bi, xx;
140
	ulong ea;
141
	long imm;
142
	static char *opc[] = {"bc", "bcl", "bca", "bcla"};
143
 
144
	getbobi(ir);
145
	USED(xx);
146
	imm = ir & 0xFFFC;
147
	if(ir & 0x08000)
148
		imm |= 0xFFFF0000;
149
	if((ir & 2) == 0) {	/* not absolute address */
150
		ea = reg.pc + imm;
151
		if(trace)
152
			itrace("%s\t%s,%s,.%s%ld\tea = #%.8lux", opc[ir&3], boname(bo), cname(bo, bi), imm<0?"":"+", imm, ea);
153
	} else {
154
		ea = imm;
155
		if(trace)
156
			itrace("%s\t%s,%s,#%.8lux", opc[ir&3], boname(bo), cname(bo, bi), ea);
157
	}
158
	if(condok(ir&0xFFFF0000, 1))
159
		ci->taken++;
160
	else
161
		ea = reg.pc + 4;
162
	if(ir & 1) {
163
		call(ea);
164
		reg.lr = reg.pc+4;
165
	}
166
	reg.pc = ea-4;
167
	/* branch delay? */
168
}
169
 
170
void
171
crop(ulong ir)
172
{
173
	int rd, ra, rb, d;
174
 
175
	getarrr(ir);
176
	if(trace)
177
		itrace("%s\tcrb%d,crb%d,crb%d", ci->name, rd, ra, rb);
178
	ra = (reg.cr & bits[ra]) != 0;
179
	rb = (reg.cr & bits[rb]) != 0;
180
	d = 0;
181
	switch(getxo(ir)) {
182
	case 257:	d = ra & rb; break;
183
	case 129:	d = ra & !rb; break;
184
	case 289:	d = ra == rb; break;
185
	case 225:	d = !(ra & rb); break;
186
	case 33:	d = !(ra | rb); break;
187
	case 449:	d = ra | rb; break;
188
	case 417:	d = ra | !rb; break;
189
	case 193:	d = ra ^ rb; break;
190
	default:	undef(ir); break;
191
	}
192
	if(d)
193
		reg.cr |= bits[rd];
194
}
195
 
196
void
197
mcrf(ulong ir)
198
{
199
	int rd, ra, rb;
200
 
201
	getarrr(ir);
202
	if(ir & 1 || rd & 3 || ra & 3 || rb)
203
		undef(ir);
204
	ra >>= 2;
205
	rd >>= 2;
206
	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, reg.cr));
207
	if(trace)
208
		itrace("mcrf\tcrf%d,crf%d", rd, ra);
209
}
210
 
211
void
212
call(ulong npc)
213
{
214
	Symbol s;
215
 
216
	if(calltree) {
217
		findsym(npc, CTEXT, &s);
218
		Bprint(bioout, "%8lux %s(", reg.pc, s.name);
219
		printparams(&s, reg.r[1]);
220
		Bprint(bioout, "from ");
221
		printsource(reg.pc);
222
		Bputc(bioout, '\n');
223
	}
224
}
225
 
226
void
227
ret(ulong npc)
228
{
229
	Symbol s;
230
 
231
	if(calltree) {
232
		findsym(npc, CTEXT, &s);
233
		Bprint(bioout, "%8lux return to #%lux %s r3=#%lux (%ld)\n",
234
					reg.pc, npc, s.name, reg.r[3], reg.r[3]);
235
	}
236
}
237
 
238
void
239
bx(ulong ir)
240
{
241
	ulong ea;
242
	long imm;
243
	static char *opc[] = {"b", "bl", "ba", "bla"};
244
 
245
	imm = ir & 0x03FFFFFC;
246
	if(ir & 0x02000000)
247
		imm |= 0xFC000000;
248
	if((ir & 2) == 0) {	/* not absolute address */
249
		ea = reg.pc + imm;
250
		if(trace)
251
			itrace("%s\t.%s%ld\tea = #%.8lux", opc[ir&3], imm<0?"":"+", imm, ea);
252
	} else {
253
		ea = imm;
254
		if(trace)
255
			itrace("%s\t#%.8lux", opc[ir&3], ea);
256
	}
257
	ci->taken++;
258
	if(ir & 1) {
259
		call(ea);
260
		reg.lr = reg.pc+4;
261
	}
262
	reg.pc = ea-4;
263
	/* branch delay? */
264
}
265
 
266
void
267
isync(ulong ir)
268
{
269
	USED(ir);
270
	if(trace)
271
		itrace("isync");
272
}