Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / diag / assembly / arch / prm / common / arch_diags.pm
CommitLineData
86530b38
AT
1# ========== Copyright Header Begin ==========================================
2#
3# OpenSPARC T2 Processor File: arch_diags.pm
4# Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5# 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6#
7# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; version 2 of the License.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21#
22# For the avoidance of doubt, and except that if any non-GPL license
23# choice is available it will apply instead, Sun elects to use only
24# the General Public License version 2 (GPLv2) at this time for any
25# software where a choice of GPL license versions is made
26# available with the language indicating that GPLv2 or any later version
27# may be used, or where a choice of which version of the GPL is applied is
28# otherwise unspecified.
29#
30# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31# CA 95054 USA or visit www.sun.com if you need additional information or
32# have any questions.
33#
34# ========== Copyright Header End ============================================
35
36package arch_diags;
37
38use strict;
39use BigIntSupport;
40use Getopt::Long;
41
42require Exporter;
43use vars qw(@ISA @EXPORT);
44
45my @ISA = qw(Exporter);
46use vars qw(%opt);
47my @EXPORT = qw(%opt);
48
49my @ld_freg = ("ld", "ldd", "ldq", "ldx");
50
51my @fregs = ( "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
52 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
53 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
54 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31" );
55
56my @fregs_dbl = ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
57 20, 22, 24, 26, 28, 30, 32, 34, 36, 38,
58 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
59 60, 62);
60
61
62my @iregs = ( "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
63 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
64 "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
65 "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31" );
66
67my @walking1_iregs = (0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x1f);
68my @walking1_imm13 = (0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20,0x40,0x80,
69 0x100, 0x200, 0x400, 0x800, 0x1000, 0x1fc0);
70
71my $ILLIMM = 0x80000000;
72
73
74#my @all_fbfcc = ("fba", "fbn", "fbu", "fbg", "fbug", "fbl", "fbul", "fblg", "fbne", "fbe", "fbue",
75# "fbge", "fbuge", "fble", "fbule", "fbo");
76my @imm22_targets = (0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x3ff000, 0x3ffff0);
77
78my @imm19_targets = (0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x7f000, 0x7fff0);
79
80my %mem_inst = (ld => 1, ldd => 1, lda => 1, ldda => 1);
81
82my %cti_inst = (
83 ba => 1, bn => 1, bne => 1, be => 1, bg => 1, ble => 1,
84 bge => 1, bl => 1, bgu => 1, bleu => 1, bcc => 1, bcs => 1,
85 bpos => 1, bneg => 1, bvc => 1, bvs => 1,
86 fba => 1, fbn => 1, fbu => 1, fbg => 1, fbug => 1, fbl => 1,
87 fbul => 1, fblg => 1, fbne => 1, fbe => 1, fbue => 1, fbge => 1,
88 fbuge => 1, fble => 1, fbule => 1, fbo => 1
89 );
90
91 %opt = (
92 name => "", # name of the diag
93 thrd_count => 1,
94 thrd_stride => 1,
95 super => 0, # run in supervisor mode
96 hyper => 0, # run in hypervisor mode
97 enboff => 0, # run in hypervisor mode
98 inst => "", # instruction to execute
99 inst_group => "", # instruction to execute
100 illinst => 0, # generate illinst trap
101 fpdis => 0, # generate fpdisable trap
102 dmisalgn => 0, # generate double-misalign trap
103 misalgn => 0, # generate misalign trap
104 dataacc => 0, # generate dataacc trap
105 privact => 0, # generate privact trap
106 vawatch => 0, # generate vamatch trap
107 seltrap => 0, # generate vamatch trap
108 alldest => 0, # try all dest regs
109 range_param => 0, # generic range.. of any type
110 mem_inst => 0,
111 cti_inst => 0
112 );
113
114
115my @options =
116 qw(
117 name=s
118 thrd_count=i
119 thrd_stride=i
120 super=i
121 hyper=i
122 enboff=i
123 inst=s
124 inst_group=s
125 illinst=i
126 fpdis=i
127 dmisalgn=i
128 misalgn=i
129 dataacc=i
130 privact=i
131 vawatch=i
132 seltrap=i
133 alldest=i
134 range_param=i
135 mem_inst=i
136 cti_inst=i
137 );
138
139sub setup_diag_options() {
140 GetOptions(\%opt, @options);
141
142 my @diag_run_args = split(/_/, $opt{name});
143 my $index = 0;
144 printf("!Diag run options :\n");
145 foreach my $diag_run_arg (@diag_run_args) {
146 if($index == 0) {
147 $opt{inst_group} = $diag_run_arg;
148 printf("!inst_group = %-20s\n", $opt{inst_group});
149 }
150 elsif($index == 1) {
151 $opt{inst} = $diag_run_arg;
152 printf("!inst = %-20s\n", $opt{inst});
153 }
154 else {
155 $opt{$diag_run_arg}=1;
156 printf("!%s = %d\n", $diag_run_arg, $opt{$diag_run_arg});
157 }
158 $index++;
159 }
160 $opt{mem_inst} = 1 if($mem_inst{$opt{inst}});
161 $opt{cti_inst} = 1 if($cti_inst{$opt{inst}});
162}
163
164my $locked_regs = 0;
165sub lock_regs() {
166 my (@regs) = @_;
167 foreach my $reg (@regs) {
168 if(($locked_regs & (0x1 << $reg)) == 0) {
169 $locked_regs |= (0x1 << $reg);
170 }
171 else {
172 printf("ERROR: reg %d is already locked\n", $reg);
173 }
174 }
175 printf("!lock_temp_reg locked regs = 0x%x\n", $locked_regs);
176}
177sub release_regs() {
178 my (@regs) = @_;
179 foreach my $reg (@regs) {
180 if($locked_regs & (0x1 << $reg)) {
181 $locked_regs ^= (0x1 << $reg);
182 }
183 else {
184 printf("ERROR: reg %d was never locked\n", $reg);
185 }
186 }
187 printf("!release_temp_reg locked regs = 0x%x\n", $locked_regs);
188}
189sub release_all_regs() {
190 $locked_regs = 0;
191 printf("!release all locked regs = 0x%x\n", $locked_regs);
192}
193
194sub pick_tmp_reg() {
195 my ($ex1, $ex2) = @_;
196 foreach my $reg (1..31) {
197 if($reg != $ex1 && $reg != $ex2 && (($locked_regs & (0x1 << $reg)) == 0)) {
198 $locked_regs |= (0x1 << $reg);
199 printf("!pick temp locked regs = 0x%x\n", $locked_regs);
200 return ($reg);
201 }
202 }
203 printf("ERROR: If here, means something went wrong in pick_tmp_reg\n");
204}
205
206sub possible_tmp_reg() {
207 my ($ex1, $ex2) = @_;
208 foreach my $reg (1..31) {
209 if($reg != $ex1 && $reg != $ex2 && (($locked_regs & (0x1 << $reg)) == 0)) {
210 printf("!possible temp locked regs = 0x%x\n", $locked_regs);
211 return ($reg);
212 }
213 }
214 printf("ERROR: If here, means something went wrong in pick_tmp_reg\n");
215}
216
217sub setx() {
218 my ($va, $tmp_reg, $dest) = @_;
219 printf("setx 0x%s, %%r%d, %%r%d\n", bigint2hex($va), $tmp_reg, $dest);
220}
221
222sub setx_label() {
223 my ($label, $tmp_reg, $dest) = @_;
224 printf("setx %s, %%r%d, %%r%d\n", $label, $tmp_reg, $dest);
225}
226
227sub mov() {
228 my ($rs1, $imm, $dest) = @_;
229 if($imm == $ILLIMM) {
230 printf("mov %%r%d, %%r%d\n", $rs1, $dest);
231 }
232 else {
233 printf("mov 0x%x, %%r%d\n", $imm, $dest);
234 }
235}
236
237sub or_regs() {
238 my ($rs1, $rs2, $imm, $dest) = @_;
239 if($imm == $ILLIMM) {
240 printf("or %%r%d, %%r%d, %%r%d\n", $rs1, $rs2, $dest);
241 }
242 else {
243 printf("or %%r%d, 0x%x, %%r%d\n", $rs1, $imm, $dest);
244 }
245}
246
247sub and_regs() {
248 my ($rs1, $rs2, $imm, $dest) = @_;
249 if($imm == $ILLIMM) {
250 printf("and %%r%d, %%r%d, %%r%d\n", $rs1, $rs2, $dest);
251 }
252 else {
253 printf("and %%r%d, 0x%x, %%r%d\n", $rs1, $imm, $dest);
254 }
255}
256
257sub add_regs() {
258 my ($rs1, $rs2, $imm, $dest) = @_;
259 if($imm == $ILLIMM) {
260 printf("add %%r%d, %%r%d, %%r%d\n", $rs1, $rs2, $dest);
261 }
262 else {
263 printf("add %%r%d, 0x%x, %%r%d\n", $rs1, $imm, $dest);
264 }
265}
266
267sub load_reg() {
268 my ($inst, $rs1, $rs2, $imm, $imm_asi, $dest_type, $dest_num) = @_;
269 if($inst eq "ldub" || $inst eq "ld" || $inst eq "ldd") {
270 &load($inst, $rs1, $rs2, $imm, $dest_type, $dest_num);
271 }
272 if($inst eq "lda" || $inst eq "ldda" || $inst eq "ldxa") {
273 &load_alt($inst, $rs1, $rs2, $imm, $imm_asi, $dest_type, $dest_num);
274 }
275}
276
277sub load() {
278 my ($inst, $rs1, $rs2, $imm, $dest_type, $dest_num) = @_;
279 if($imm == $ILLIMM) {
280 printf("%s [%%r%d+%%r%d], %s%d\n", $inst, $rs1, $rs2, $dest_type, $dest_num);
281 }
282 else {
283 printf("%s [%%r%d+0x%x], %s%d\n", $inst, $rs1, $imm, $dest_type, $dest_num);
284 }
285}
286
287sub store() {
288 my ($inst, $src_type, $src_num, $rs1, $rs2, $imm) = @_;
289 if($imm == $ILLIMM) {
290 printf("%s %s%d, [%%r%d+%%r%d]\n", $inst, $src_type, $src_num, $rs1, $rs2);
291 }
292 else {
293 printf("%s %s%d, [%%r%d+0x%x]\n", $inst, $src_type, $src_num, $rs1, $imm);
294 }
295}
296
297sub load_alt() {
298 my ($inst, $rs1, $rs2, $imm, $imm_asi, $dest_type, $dest_num) = @_;
299 if($imm == $ILLIMM) {
300 if($imm_asi == $ILLIMM) {
301 printf("%s [%%r%d+%%r%d] %%asi, %s%d\n", $inst, $rs1, $rs2, $dest_type, $dest_num);
302 }
303 else {
304 printf("%s [%%r%d+%%r%d] 0x%x, %s%d\n", $inst, $rs1, $rs2, $imm_asi, $dest_type, $dest_num);
305 }
306 }
307 else {
308 if($imm_asi == $ILLIMM) {
309 printf("%s [%%r%d+0x%x] %%asi, %s%d\n", $inst, $rs1, $imm, $dest_type, $dest_num);
310 }
311 else {
312 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
313 printf("wr %%r0, 0x%x, %%asi\n", $imm_asi);
314 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
315 printf("%s [%%r%d+0x%x] %%asi, %s%d\n", $inst, $rs1, $imm, $dest_type, $dest_num);
316 }
317 }
318}
319
320sub store_alt() {
321 my ($inst, $dest_type, $dest_num, $rs1, $rs2, $imm, $imm_asi) = @_;
322
323 if($imm == $ILLIMM) {
324 if($imm_asi == $ILLIMM) {
325 printf("%s %s%d, [%%r%d+%%r%d] %%asi\n", $inst, $dest_type, $dest_num, $rs1, $rs2);
326 }
327 else {
328 printf("%s %s%d, [%%r%d+%%r%d] 0x%x\n", $inst, $dest_type, $dest_num, $rs1, $rs2, $imm_asi);
329 }
330 }
331 else {
332 if($imm_asi == $ILLIMM) {
333 printf("%s %s%d, [%%r%d+0x%x] %%asi\n", $inst, $dest_type, $dest_num, $rs1, $imm);
334 }
335 else {
336 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
337 printf("wr %%r0, 0x%x, %%asi\n", $imm_asi);
338 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
339 printf("%s %s%d, [%%r%d+0x%x] %%asi\n", $inst, $dest_type, $dest_num, $rs1, $imm);
340 }
341 }
342
343}
344
345sub cas() {
346 my ($inst, $rs1, $rs2, $imm, $dest_type, $dest_num) = @_;
347 if($imm == $ILLIMM) {
348 printf("%s [%%r%d], %%r%d, %s%d\n", $inst, $rs1, $rs2, $dest_type, $dest_num);
349 }
350 else {
351 my $tmp1 = &pick_tmp_reg();
352 &add_regs($rs1, 0, $imm, $tmp1);
353 printf("%s [%%r%d], %%r%d, %s%d\n", $inst, $tmp1, $rs2, $dest_type, $dest_num);
354 &release_regs($tmp1);
355 }
356}
357
358sub cas_alt() {
359 my ($inst, $rs1, $rs2, $imm, $imm_asi, $dest_type, $dest_num) = @_;
360 if($imm == $ILLIMM) {
361 if($imm_asi == $ILLIMM) {
362 printf("%s [%%r%d] %%asi, %%r%d, %s%d\n", $inst, $rs1, $rs2, $dest_type, $dest_num);
363 }
364 else {
365 printf("%s [%%r%d] 0x%x, %%r%d, %s%d\n", $inst, $rs1, $imm_asi, $rs2, $dest_type, $dest_num);
366 }
367 }
368 else {
369 my $tmp1 = &pick_tmp_reg();
370 &add_regs($rs1, 0, $imm, $tmp1);
371 if($imm_asi == $ILLIMM) {
372 printf("%s [%%r%d] %%asi, %%r%d, %s%d\n", $inst, $tmp1, $rs2, $dest_type, $dest_num);
373 }
374 else {
375 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
376 printf("wr %%r0, 0x%x, %%asi\n", $imm_asi);
377 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
378 printf("%s [%%r%d] %%asi, %%r%d, %s%d\n", $inst, $tmp1, $rs2, $dest_type, $dest_num);
379 }
380 &release_regs($tmp1);
381 }
382}
383
384# va == net va
385# imm == required imm in va
386sub setup_addr_in_rs1_rs2() {
387 my ($va, $rs1, $rs2, $imm, $err_ref) = @_;
388 my ($tmp_reg) = 0;
389
390 $$err_ref = 0;
391 if($imm != $ILLIMM) {
392 if($rs1 != 0) {
393 my ($remainder) = $va;
394 if($imm & 0x1000) {
395 $imm |= 0xffffe000;
396 $imm = ~$imm; $imm += 1; # 2's complement
397 $remainder = $va + $imm;
398 }
399 else {
400 $remainder = $va - $imm;
401 }
402 $tmp_reg = &pick_tmp_reg($rs1);
403 &lock_regs($rs1);
404 &setx($remainder, $tmp_reg, $rs1);
405 &release_regs($tmp_reg);
406 return $va;
407 }
408 else {
409 return $imm;
410 }
411 }
412
413 if($rs1 == 0 && $rs2 == 0) {
414 # no init needed, load will come from 0x0.
415 return 0;
416 }
417 elsif($rs1 == 0) {
418 $tmp_reg = &pick_tmp_reg($rs2);
419 &setx($va, $tmp_reg, $rs2);
420 &lock_regs($rs2);
421 &release_regs($tmp_reg);
422 }
423 elsif($rs2 == 0) {
424 $tmp_reg = &pick_tmp_reg($rs1);
425 &setx($va, $tmp_reg, $rs1);
426 &lock_regs($rs1);
427 &release_regs($tmp_reg);
428 }
429 else {
430 $tmp_reg = &pick_tmp_reg($rs1, $rs2);
431 my ($half_addr) = 0;
432 if($rs1 == $rs2) {
433 if($va%2 != 0) {
434 $$err_ref = 1; # Can't get this addr setup.
435 return $va;
436 }
437 else {
438 $half_addr = $va/2;
439 }
440 }
441 else {
442 $half_addr = int($va/2 + $va/4);
443 }
444 my ($other_half) = $va - $half_addr;
445 &setx($half_addr, $tmp_reg, $rs1);
446 &setx($other_half, $tmp_reg, $rs2);
447 &lock_regs($rs1);
448 &lock_regs($rs2) if($rs1 != $rs2);
449 &release_regs($tmp_reg);
450 }
451 return $va;
452}
453
454sub gen_instr_sec() {
455
456# printf("SECTION .BIG_MAIN TEXT_VA=0x30000000\n");
457 printf("SECTION .BIG_MAIN TEXT_VA=0x20000000\n");
458 printf("attr_text {\n");
459 printf("Name = .BIG_MAIN,\n");
460# printf("VA= 0x30000000,\n");
461 printf("VA= 0x20000000,\n");
462# printf("RA= 0x120000000,\n");
463 printf("RA= 0x130000000,\n");
464# printf("PA=ra2pa\(0x120000000,0\),\n");
465 printf("PA=ra2pa\(0x130000000,0\),\n");
466 printf("compressimage,\n");
467# printf("part_0_i_ctx_nonzero_ps0_tsb,\n");
468 printf("part_0_ctx_nonzero_tsb_config_1,\n");
469 printf("TTE_G=1, TTE_Context=0x44, TTE_V=1, TTE_Size=5, TTE_Size_Ptr=0, TTE_NFO=0,\n");
470 printf("TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0,\n");
471 printf("TTE_L=0, TTE_CP=1, TTE_CV=0, TTE_E=0, TTE_P=0, TTE_W=1\n");
472 printf("}\n");
473 if($opt{hyper}) {
474 printf("attr_text {\n");
475 printf("Name = .BIG_MAIN,\n");
476 printf("hypervisor\n");
477 printf("}\n");
478 }
479}
480
481sub gen_data_sec() {
482 my ($data_va, $last_data_va, $dataacc, $super) = @_;
483
484 printf("SECTION RAND_DATA%s DATA_VA=0x%s\n", bigint2hex($data_va), bigint2hex($data_va));
485 printf("attr_data {\n");
486 printf(" Name = RAND_DATA%s,\n",bigint2hex($data_va));
487 if($opt{hyper} && (($opt{inst_group} ne "asi") ||
488 (($opt{inst} ne "0x10") && ($opt{inst} ne "0x11") &&
489 ($opt{inst} ne "0x14") && ($opt{inst} ne "0x15") &&
490 ($opt{inst} ne "0x16") && ($opt{inst} ne "0x17") &&
491 ($opt{inst} ne "0x1c") && ($opt{inst} ne "0x1d") &&
492 ($opt{inst} ne "0x1e") && ($opt{inst} ne "0x1f") &&
493 ($opt{inst} ne "0x22") && ($opt{inst} ne "0x23") &&
494 ($opt{inst} ne "0x26") && ($opt{inst} ne "0x2e") &&
495 ($opt{inst} ne "0x2a") && ($opt{inst} ne "0x2b") &&
496 ($opt{inst} ne "0x18") && ($opt{inst} ne "0x19")))) {
497 printf("hypervisor\n");
498 }
499 else {
500 printf(" RA=0x%s,\n",bigint2hex($data_va));
501 if($dataacc) {
502 printf(" tsbonly,\n");
503 }
504 else {
505 if(($data_va >> 39) & 0x1) { #if bit39 on va is set, make it equal to PA
506 printf(" PA=0x%s,\n", bigint2hex($data_va));
507 }
508 else {
509 printf(" PA=ra2pa\(0x%s,0\),\n", bigint2hex($data_va));
510 }
511 }
512# printf(" part_0_d_ctx_nonzero_ps0_tsb, \n");
513 printf(" part_0_ctx_nonzero_tsb_config_0, \n");
514 if((($opt{inst_group} eq "asi") && (($opt{inst} eq "0x4") || ($opt{inst} eq "0xc") ||
515 ($opt{inst} eq "0x24") || ($opt{inst} eq "0x26") ||
516 ($opt{inst} eq "0x2c") || ($opt{inst} eq "0x2e") ||
517 ($opt{inst} eq "0x27") || ($opt{inst} eq "0x2f"))) ||
518 (($opt{inst_group} eq "ldst") && ($opt{inst} eq "tl1"))) {
519# printf(" part_0_d_ctx_zero_ps0_tsb, \n");
520 printf(" part_0_ctx_zero_tsb_config_0, \n");
521 }
522 if(($opt{inst_group} eq "asi") && (($opt{inst} eq "0x11") || ($opt{inst} eq "0x19") ||
523 ($opt{inst} eq "0x81") || ($opt{inst} eq "0x83") ||
524 ($opt{inst} eq "0x89") || ($opt{inst} eq "0x8b") ||
525 ($opt{inst} eq "0x17") || ($opt{inst} eq "0x1f") ||
526 ($opt{inst} eq "0x23") || ($opt{inst} eq "0x2b") ||
527 ($opt{inst} eq "0xe3") || ($opt{inst} eq "0xeb") ||
528 ($opt{inst} eq "0xf1") || ($opt{inst} eq "0xf9"))) {
529 printf("TTE_Context=SCONTEXT\n");
530 }
531 else {
532 printf("TTE_Context=PCONTEXT\n");
533 }
534 printf(" TTE_G=1, TTE_Size=0x0, \n");
535 if(($opt{inst_group} eq "asi") && (($opt{inst} eq "0x82") || ($opt{inst} eq "0x83") ||
536 ($opt{inst} eq "0x8a") || ($opt{inst} eq "0x8b"))) {
537 printf("TTE_NFO=1,\n");
538 }
539 else {
540 printf("TTE_NFO=0,\n");
541 }
542 printf(" TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0,\n");
543 printf(" TTE_L=0, TTE_CP=1, TTE_CV=0, TTE_E=0, ");
544 if(($dataacc && $opt{inst_group} ne "asi") || $opt{super}) {
545 if(($opt{inst_group} eq "asi") && ($opt{inst} eq "0x10" || $opt{inst} eq "0x11" ||
546 $opt{inst} eq "0x18" || $opt{inst} eq "0x19" ||
547 $opt{inst} eq "0x22" || $opt{inst} eq "0x23" ||
548 $opt{inst} eq "0x2a" || $opt{inst} eq "0x2b" ||
549 $opt{inst} eq "0x80" || $opt{inst} eq "0x81" ||
550 $opt{inst} eq "0x82" || $opt{inst} eq "0x83" ||
551 $opt{inst} eq "0x88" || $opt{inst} eq "0x89" ||
552 $opt{inst} eq "0x8a" || $opt{inst} eq "0x8b")) {
553 printf("TTE_P=0, TTE_W=1, TTE_V=1\n");
554 }
555 else {
556 printf("TTE_P=1, TTE_W=1, TTE_V=1\n");
557 }
558 }
559 else {
560 printf("TTE_P=0, TTE_W=1, TTE_V=1\n");
561 }
562 }
563 printf(" }\n");
564 printf(".data\n");
565 printf(".global data_sec%s\n",bigint2hex($data_va));
566 printf("normal_addr_range_data%s:\n",bigint2hex($data_va));
567 if($dataacc == 0) {
568 for (my $i=0; $i<($last_data_va-$data_va)/4; $i++) {
569 printf(".word 0x%x\n", int(rand(0xffffffff)));
570 }
571 }
572 else {
573 printf(".skip %d\n", ($last_data_va-$data_va));
574 printf(".byte 0x%x\n", int(rand(0xff)));
575 }
576
577 printf(".end\n");
578}
579
580
581sub gen_high_data_sec() {
582 my ($dataacc, $super) = @_;
583
584# printf("SECTION RAND_DATAffffffffffffe000 DATA_VA=0xffffffffffffe000\n");
585 printf("SECTION RAND_DATAffffffffff838000 DATA_VA=0xffffffffff838000\n");
586 printf("attr_data {\n");
587# printf(" Name = RAND_DATAffffffffffffe000,\n");
588 printf(" Name = RAND_DATAffffffffff838000,\n");
589 if($opt{hyper}) {
590 printf("hypervisor\n");
591 }
592 else {
593# printf(" RA=0x20010000,\n");
594 printf(" RA=0x17f000000,\n");
595 if($dataacc) {
596 printf(" tsbonly,\n");
597 }
598 else {
599# printf(" PA=ra2pa\(0x20010000,0\),\n");
600 printf(" PA=ra2pa\(0x17f000000,0\),\n");
601 }
602 if($super) {
603# printf(" part_0_d_ctx_nonzero_ps0_tsb, TTE_Context=PCONTEXT\n");
604 printf(" part_0_ctx_nonzero_tsb_config_2, TTE_Context=PCONTEXT\n");
605 }
606 else {
607# printf(" part_0_d_ctx_nonzero_ps0_tsb, TTE_Context=PCONTEXT\n");
608 printf(" part_0_ctx_nonzero_tsb_config_2, TTE_Context=PCONTEXT\n");
609 }
610 printf(" TTE_G=1, TTE_Size=0x0, TTE_NFO=0,\n");
611 printf(" TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0,\n");
612 printf(" TTE_L=0, TTE_CP=1, TTE_CV=0, TTE_E=0, ");
613 if($dataacc) {
614 if($opt{super}) {
615 printf("TTE_P=0, TTE_W=1, TTE_V=0\n");
616 }
617 else {
618 printf("TTE_P=1, TTE_W=1, TTE_V=1\n");
619 }
620 }
621 else {
622 printf("TTE_P=0, TTE_W=1, TTE_V=1\n");
623 }
624 }
625 printf(" }\n");
626 printf(".data\n");
627# printf(".global data_secffffffffffffe000\n");
628 printf(".global data_secffffffffff838000\n");
629# printf("normal_addr_range_dataffffffffffffe000:\n");
630 printf("normal_addr_range_dataffffffffff838000:\n");
631 if($dataacc == 0) {
632 for (my $i=0; $i<8188/4; $i++) {
633 printf(".word 0x%x\n", int(rand(0xffffffff)));
634 }
635 }
636 else {
637 printf(".skip 8180\n");
638 printf(".byte 0x%x\n", int(rand(0xff)));
639 }
640
641 printf(".end\n");
642}
643
644sub gen_scratch_mem_area() {
645# printf("SECTION SCRATCH_MEM DATA_VA=0x1ffffe000\n");
646 printf("SECTION SCRATCH_MEM DATA_VA=0x17fff0000\n");
647# printf("attr_data {\n");
648# printf(" Name = SCRATCH_MEM,\n");
649# printf(" hypervisor\n");
650# printf(" }\n");
651 printf("attr_data {\n");
652 printf(" Name = SCRATCH_MEM,\n");
653# printf(" RA=0x1ffffe000,\n");
654 printf(" RA=0x17fff0000,\n");
655# printf(" PA=ra2pa\(0x1ffffe000,0\),\n");
656 printf(" PA=ra2pa\(0x17fff0000,0\),\n");
657# printf(" part_0_d_ctx_nonzero_ps0_tsb, \n");
658 printf(" part_0_ctx_nonzero_tsb_config_1, \n");
659# printf(" part_0_d_ctx_zero_ps0_tsb, \n");
660 printf(" part_0_ctx_zero_tsb_config_1, \n");
661 printf(" TTE_Context=PCONTEXT\n");
662 printf(" TTE_G=1, TTE_Size=0x0, TTE_NFO=0,\n");
663 printf(" TTE_IE=0, TTE_Soft2=0, TTE_Diag=0, TTE_Soft=0,\n");
664 printf(" TTE_L=0, TTE_CP=1, TTE_CV=0, TTE_E=0, ");
665 printf(" TTE_P=0, TTE_W=1, TTE_V=1\n");
666 printf(" }\n");
667 printf(".data\n");
668 printf(".global scratch_mem\n");
669 printf("scratch_mem:\n");
670 for (my $i=0; $i<1024/4; $i++) {
671 printf(".word 0x%x\n", int(rand(0xffffffff)));
672 }
673}
674
675sub setup_va_watchpoint() {
676 my ($addr, $rd_en, $wr_en) = @_;
677
678 if(($opt{enboff} == 0) && ($opt{hyper} == 0)) {
679 printf("ta T_CHANGE_HPRIV\n")
680 }
681 elsif ($opt{enboff} && ($opt{super} == 0)) {
682 printf("ta T_CHANGE_PRIV\n")
683 }
684 else {
685 # hyper mode, or enboff.super mode requires nothing.
686 }
687 my $tmp_reg_lsu_ctl = &pick_tmp_reg();
688 &load_alt("ldxa", 0, 0, $ILLIMM, 0x45, "%r", $tmp_reg_lsu_ctl);
689 my $tmp1 = &pick_tmp_reg();
690 my $tmp2 = &pick_tmp_reg();
691 my $tmp_rst_mask = hex2bigint("0x000fffff");
692 &setx($tmp_rst_mask, $tmp1, $tmp2);
693 &and_regs($tmp2, $tmp_reg_lsu_ctl, $ILLIMM, $tmp_reg_lsu_ctl);
694
695 my $ctl_reg_mask = hex2bigint("0x7fe000000");
696 $ctl_reg_mask |= ($wr_en << 23);
697 $ctl_reg_mask |= ($rd_en << 24);
698 &setx($ctl_reg_mask, $tmp1, $tmp2);
699 &or_regs($tmp_reg_lsu_ctl, $tmp2, $ILLIMM, $tmp_reg_lsu_ctl);
700 &store_alt("stxa", "%r", $tmp_reg_lsu_ctl, 0, 0, $ILLIMM, 0x45);
701
702 #now setup addr
703 if($rd_en || $wr_en) { # only then address matters
704 my $big_addr = Math::BigInt->new($addr);
705 if(($big_addr & 0xfffff000) == 0x1000) {
706 my $big_tmp = Math::BigInt->new(0xffffffff);
707 $big_tmp <<= 32;
708 $big_addr = $big_tmp | 0xffffe000 | $big_addr;
709 }
710 &setx($big_addr, $tmp1, $tmp2);
711 &mov(0, 0x38, $tmp1);
712 &store_alt("stxa", "%r", $tmp2, $tmp1, 0, $ILLIMM, 0x58);
713 }
714 if(($opt{hyper} == 0) && ($opt{enboff} == 0)) {
715 printf("ta T_CHANGE_NONHPRIV\n")
716 }
717 elsif ($opt{enboff} && ($opt{super} == 0)) {
718 printf("ta T_CHANGE_NONPRIV\n")
719 }
720 else {
721 # hyper mode, or enboff.super mode requires nothing.
722 }
723 &release_regs($tmp_reg_lsu_ctl, $tmp1, $tmp2);
724}
725
726sub setup_tte_entry() {
727 my ($addr) = @_;
728
729 printf("!func: setup_tte_entry : 0x%x\n", $addr);
730
731 my $err = 0;
732 my $tmp1 = &pick_tmp_reg();
733 my $tmp2 = &pick_tmp_reg();
734 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
735 &setx($addr, $tmp1, $tmp2);
736 &load("ldub", $tmp2, 0, $ILLIMM, "%r", 0);
737 &release_regs($tmp1, $tmp2);
738 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
739}
740
741sub gen_all_ldf() {
742 my ($ldf_inst, $next_addr_ref, $next_0addr_ref, $all_dest, $misalgn_offset, $vawatch, $preloadtlb) = @_;
743
744 my $factor = 1;
745 $factor = 2 if($ldf_inst eq "ldd" || $ldf_inst eq "ldda");
746
747 my @fdest = ();
748 if($all_dest) {
749 @fdest = (0..31);
750 }
751 else {
752 @fdest = (0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x1f);
753 }
754
755 my ($ldf_dest, $rs1, $rs2, $err);
756 foreach $ldf_dest (@fdest) { #pick dest freg
757 my $dest = $ldf_dest*$factor;
758 foreach $rs1 (@walking1_iregs) { #mem addr combination rs1
759 my @rep_rs2 = (0, $rs1, 31);
760 foreach $rs2 (@rep_rs2) { #mem addr combination rs2
761 my ($imm) = $ILLIMM;
762 my $setup_va = &setup_addr_in_rs1_rs2($$next_addr_ref+$misalgn_offset, $rs1, $rs2, $imm, \$err);
763 if($err == 0) {
764 if($setup_va == ($$next_addr_ref+$misalgn_offset)) {
765 $$next_addr_ref += (4*$factor);
766 }
767 else {
768 push(@$next_0addr_ref, $setup_va);
769 }
770 if($misalgn_offset == 0 || $setup_va != 0) {
771 &setup_tte_entry($setup_va) if($preloadtlb);
772 &setup_va_watchpoint($setup_va, 1, 0) if($vawatch);
773 &load_reg($ldf_inst, $rs1, $rs2, $imm, 0x88, "%f", $dest);
774 &setup_va_watchpoint($setup_va, 0, 0) if($vawatch);
775 printf("\n");
776 }
777 }
778 &release_all_regs();
779 }
780
781 my @rep_imm13 = (0, 0x800, 0x1000, 0x1fc0);
782 foreach my $imm (@rep_imm13) { #mem addr combination imm
783 my $setup_va = &setup_addr_in_rs1_rs2($$next_addr_ref+$misalgn_offset, $rs1, $rs2, $imm+$misalgn_offset, \$err);
784 if($err == 0) {
785 if($setup_va == ($$next_addr_ref+$misalgn_offset)) {
786 $$next_addr_ref += (4*$factor);
787 }
788 else {
789 push(@$next_0addr_ref, $setup_va);
790 }
791 if($misalgn_offset == 0 || $setup_va != 0) {
792 &setup_tte_entry($setup_va) if($preloadtlb);
793 &setup_va_watchpoint($setup_va, 1, 0) if($vawatch);
794 &load_reg($ldf_inst, $rs1, $rs2, $imm+$misalgn_offset, 0x88, "%f", $dest);
795 &setup_va_watchpoint($setup_va, 0, 0) if($vawatch);
796 printf("\n");
797 }
798 }
799 &release_all_regs();
800 }
801 }
802
803 foreach $rs2 (@walking1_iregs) { #mem addr combination rs1
804 my @rep_rs1 = (0, $rs2, 31);
805 foreach $rs1 (@rep_rs1) { #mem addr combination rs2
806 my ($imm) = $ILLIMM;
807 my $setup_va = &setup_addr_in_rs1_rs2($$next_addr_ref+$misalgn_offset, $rs1, $rs2, $imm, \$err);
808 if($err == 0) {
809 if($setup_va == ($$next_addr_ref+$misalgn_offset)) {
810 $$next_addr_ref += (4*$factor);
811 }
812 else {
813 push(@$next_0addr_ref, $setup_va);
814 }
815 if($misalgn_offset == 0 || $setup_va != 0) {
816 &setup_tte_entry($setup_va) if($preloadtlb);
817 &setup_va_watchpoint($setup_va, 1, 0) if($vawatch);
818 &load_reg($ldf_inst, $rs1, $rs2, $imm, 0x88, "%f", $dest);
819 &setup_va_watchpoint($setup_va, 0, 0) if($vawatch);
820 printf("\n");
821 }
822 }
823 &release_all_regs();
824 }
825 }
826
827 foreach my $imm (@walking1_imm13) { #mem addr combination rs1
828 my @rep_rs1 = (0, 31);
829 foreach $rs1 (@rep_rs1) { #mem addr combination rs2
830 if($rs1 == 0 && ($imm & 0x3f)) {
831 #skip
832 }
833 else {
834 my $setup_va = &setup_addr_in_rs1_rs2($$next_addr_ref+$misalgn_offset, $rs1, $rs2, $imm+$misalgn_offset, \$err);
835 if($err == 0) {
836 if($setup_va == ($$next_addr_ref+$misalgn_offset)) {
837 $$next_addr_ref += (4*$factor);
838 }
839 else {
840 push(@$next_0addr_ref, $setup_va);
841 }
842 if($misalgn_offset == 0 || $setup_va != 0) {
843 &setup_tte_entry($setup_va) if($preloadtlb);
844 &setup_va_watchpoint($setup_va, 1, 0) if($vawatch);
845 &load_reg($ldf_inst, $rs1, $rs2, $imm+$misalgn_offset, 0x88, "%f", $dest);
846 &setup_va_watchpoint($setup_va, 0, 0) if($vawatch);
847 printf("\n");
848 }
849 }
850 &release_all_regs();
851 }
852 }
853 }
854 }
855}
856
857
858sub gen_all_fbfcc() {
859 my ($th_id, $inst, $inst_group) = @_;
860 foreach my $taken (0..1) {
861 foreach my $cc_combo (0..3) {
862 my $setup_ok = &setup_fcc_for_fbpfcc($inst, $inst_group, $taken, 0, $cc_combo, $th_id);
863 if($setup_ok) {
864 foreach my $annul (0..1) {
865 foreach my $target (@imm22_targets) {
866 &gen_fbpfcc($inst, $inst_group, $annul, 0, 0, $cc_combo, $target, $taken, $th_id);
867 }
868 }
869 }
870 }
871 }
872}
873
874sub gen_all_fbpfcc() {
875 my ($th_id, $inst, $inst_group) = @_;
876 foreach my $taken (0..1) {
877 foreach my $which_fcc (0..3) {
878 foreach my $cc_combo (0..3) {
879 my $setup_ok = &setup_fcc_for_fbpfcc($inst, $inst_group, $taken, $which_fcc, $cc_combo, $th_id);
880 if($setup_ok) {
881 foreach my $ptn (0..1) {
882 foreach my $annul (0..1) {
883 foreach my $target (@imm19_targets) {
884 &gen_fbpfcc($inst, $inst_group, $annul, $ptn, $which_fcc, $cc_combo, $target, $taken, $th_id);
885 }
886 }
887 }
888 }
889 }
890 }
891 }
892}
893
894sub gen_fbpfcc() {
895 my ($inst, $inst_group, $annul, $ptn, $which_fcc, $cc_combo, $target, $taken, $th_id) = @_;
896
897 return if(($taken == 0) && ($opt{fpdis} == 0) && ($inst eq "fba"));
898 return if(($taken == 1) && ($opt{fpdis} == 0) && ($inst eq "fbn"));
899
900 my $target_limit = 0x200000;
901 $target_limit = 0x40000 if($inst_group eq "fbpfcc");
902
903 if($taken && ($opt{fpdis} == 0) && $target == 0) {
904 #taken branch on self will be inf-loop
905 }
906 else {
907 if($target & $target_limit) {
908 printf("setx th%d_nxt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x, %%g2, %%g3\n", $th_id, $inst, $which_fcc, $cc_combo,
909 $ptn, $annul, $taken, $target);
910 printf("th%d_tgt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target);
911 printf("jmp %%g3\n");
912 printf("nop\n");
913 }
914
915 printf("th%d_nxt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target);
916 printf("th%d_tgt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target) if($target == 0);
917 if($target & $target_limit) {
918 printf("add %%g3, 0xc, %%g3\n");
919 }
920 printf("%s", $inst);
921 printf(",a") if($annul);
922 printf(",pt") if($ptn == 1 && ($inst_group eq "fbpfcc"));
923 printf(",pn") if($ptn == 0 && ($inst_group eq "fbpfcc"));
924 printf(" %%fcc%d, ", $which_fcc) if($inst_group eq "fbpfcc");
925 printf(" th%d_tgt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target);
926 if($target == 1) {
927 printf("th%d_tgt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target);
928 printf("nop ! delay slot & branch target\n");
929 printf("\n");
930 }
931 else {
932 if(($inst eq "fba" || $inst eq "fbn") && $annul && ($opt{fpdis} == 0)) {
933 #eat annuled instr(make it illegal)
934 printf(".word 0x0\n");
935 }
936 elsif(($taken == 0) && $annul && ($opt{fpdis} == 0)) {
937 #eat annuled instr(make it illegal)
938 printf(".word 0x0\n");
939 }
940 else {
941 printf("nop ! delay slot\n");
942 }
943 if(($target != 0) && (($target & $target_limit) == 0)) {
944 if(($target > 2) && (($taken == 0) || $opt{fpdis})) {
945 printf("call th%d_tgt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target);
946 printf("nop\n");
947 printf(".skip %d\n", ($target-4)*4) if($target > 4);
948 }
949 else {
950 printf(".skip %d\n", ($target-2)*4) if($target > 2);
951 }
952 printf("th%d_tgt_%s_fcc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_fcc, $cc_combo, $ptn, $annul, $taken, $target);
953 printf("nop ! branch target\n");
954 }
955 printf("\n");
956 }
957 }
958}
959
960sub setup_fcc_for_fbpfcc() {
961 my ($inst, $inst_group, $taken, $which_fcc, $cc_combo, $th_id) = @_;
962
963 my $ext_on = 0;
964 $ext_on = 1 if($inst_group eq "fbpfcc");
965
966 my $value = $cc_combo;
967 my $cc_E = 0;
968 my $cc_L = 1;
969 my $cc_G = 2;
970 my $cc_U = 3;
971
972 if($inst eq "fba" || $inst eq "fbn") {
973 # all cc-combos are ok
974 }
975 elsif($inst eq "fbu") {
976 return 0 if(($taken == 1) && ($value != $cc_U));
977 return 0 if(($taken == 0) && ($value == $cc_U));
978 }
979 elsif($inst eq "fbg") {
980 return 0 if(($taken == 1) && ($value != $cc_G));
981 return 0 if(($taken == 0) && ($value == $cc_G));
982 }
983 elsif($inst eq "fbug") {
984 return 0 if(($taken == 1) && (($value != $cc_U) && ($value != $cc_G)));
985 return 0 if(($taken == 0) && (($value == $cc_U) || ($value == $cc_G)));
986 }
987 elsif($inst eq "fbl") {
988 return 0 if(($taken == 1) && ($value != $cc_L));
989 return 0 if(($taken == 0) && ($value == $cc_L));
990 }
991 elsif($inst eq "fbul") {
992 return 0 if(($taken == 1) && (($value != $cc_L) && ($value != $cc_U)));
993 return 0 if(($taken == 0) && (($value == $cc_L) || ($value == $cc_U)));
994 }
995 elsif($inst eq "fblg") {
996 return 0 if(($taken == 1) && (($value != $cc_L) && ($value != $cc_G)));
997 return 0 if(($taken == 0) && (($value == $cc_L) || ($value == $cc_G)));
998 }
999 elsif($inst eq "fbne") {
1000 return 0 if(($taken == 1) && (($value != $cc_L) && ($value != $cc_G) && ($value != $cc_U)));
1001 return 0 if(($taken == 0) && (($value == $cc_L) || ($value == $cc_G) || ($value == $cc_U)));
1002 }
1003 elsif($inst eq "fbe") {
1004 return 0 if(($taken == 1) && ($value != $cc_E));
1005 return 0 if(($taken == 0) && ($value == $cc_E));
1006 }
1007 elsif($inst eq "fbue") {
1008 return 0 if(($taken == 1) && (($value != $cc_U) && ($value != $cc_E)));
1009 return 0 if(($taken == 0) && (($value == $cc_U) || ($value == $cc_E)));
1010 }
1011 elsif($inst eq "fbge") {
1012 return 0 if(($taken == 1) && (($value != $cc_G) && ($value != $cc_E)));
1013 return 0 if(($taken == 0) && (($value == $cc_G) || ($value == $cc_E)));
1014 }
1015 elsif($inst eq "fbuge") {
1016 return 0 if(($taken == 1) && (($value != $cc_U) && ($value != $cc_G) && ($value != $cc_E)));
1017 return 0 if(($taken == 0) && (($value == $cc_U) || ($value == $cc_G) || ($value == $cc_E)));
1018 }
1019 elsif($inst eq "fble") {
1020 return 0 if(($taken == 1) && (($value != $cc_E) && ($value != $cc_L)));
1021 return 0 if(($taken == 0) && (($value == $cc_E) || ($value == $cc_L)));
1022 }
1023 elsif($inst eq "fbule") {
1024 return 0 if(($taken == 1) && (($value != $cc_E) && ($value != $cc_L) && ($value != $cc_U)));
1025 return 0 if(($taken == 0) && (($value == $cc_E) || ($value == $cc_L) || ($value == $cc_U)));
1026 }
1027 elsif($inst eq "fbo") {
1028 return 0 if(($taken == 1) && (($value != $cc_E) && ($value != $cc_L) && ($value != $cc_G)));
1029 return 0 if(($taken == 0) && (($value == $cc_E) || ($value == $cc_L) || ($value == $cc_G)));
1030 }
1031 else {
1032 printf("ERROR: bad instruction type\n");
1033 return 0;
1034 }
1035 my $others = (~$value) & 0x3;
1036
1037 if($which_fcc == 0) {
1038 &setup_xfsr_fcc($ext_on, $others, $others, $others, $value, $th_id);
1039 }
1040 if($which_fcc == 1) {
1041 &setup_xfsr_fcc($ext_on, $others, $others, $value, $others, $th_id);
1042 }
1043 if($which_fcc == 2) {
1044 &setup_xfsr_fcc($ext_on, $others, $value, $others, $others, $th_id);
1045 }
1046 if($which_fcc == 3) {
1047 &setup_xfsr_fcc($ext_on, $value, $others, $others, $others, $th_id);
1048 }
1049 return 1;
1050}
1051
1052sub setup_xfsr_fcc() {
1053 my ($ext_on, $fcc3, $fcc2, $fcc1, $fcc0, $th_id) = @_;
1054
1055 my $big_value = Math::BigInt->new(($fcc3<<4) | ($fcc2<<2) | ($fcc1));
1056 $big_value <<=32 ;
1057 $big_value |= ($fcc0<<10);
1058
1059 if($ext_on) {
1060 printf("stx %%fsr, [%%g0+%d]\n", $th_id*8);
1061 }
1062 else {
1063 printf("st %%fsr, [%%g0+%d]\n", $th_id*4);
1064 }
1065 my $tmp_fsr = &pick_tmp_reg();
1066 if($ext_on) {
1067 printf("ldx [%%g0+%d], %%r%d\n", $th_id*8, $tmp_fsr);
1068 }
1069 else {
1070 printf("ld [%%g0+%d], %%r%d\n", $th_id*4, $tmp_fsr);
1071 }
1072 my $tmp1 = &pick_tmp_reg();
1073 my $tmp2 = &pick_tmp_reg();
1074 &setx(0xfffff3ff, $tmp1, $tmp2);
1075 &and_regs($tmp_fsr, $tmp2, $ILLIMM, $tmp_fsr);
1076 &setx($big_value, $tmp1, $tmp2);
1077 &or_regs($tmp_fsr, $tmp2, $ILLIMM, $tmp_fsr);
1078 if($ext_on) {
1079 printf("stx %%r%d, [%%g0+%d]\n", $tmp_fsr, $th_id*8);
1080 printf("ldx [%%g0+%d], %%fsr\n", $th_id*8);
1081 }
1082 else {
1083 printf("st %%r%d, [%%g0+%d]\n", $tmp_fsr, $th_id*4);
1084 printf("ld [%%g0+%d], %%fsr\n", $th_id*4);
1085 }
1086 &release_regs($tmp_fsr, $tmp1, $tmp2);
1087}
1088
1089
1090
1091sub gen_all_bicc() {
1092 my ($th_id, $inst, $inst_group) = @_;
1093 foreach my $taken (0..1) {
1094 my @cc_combo_range = (0..15);
1095 foreach my $cc_combo (@cc_combo_range) {
1096 my $setup_ok = &setup_cc_for_bpcc($inst, $inst_group, $taken, 0, $cc_combo, $th_id);
1097 if($setup_ok) {
1098 foreach my $annul (0..1) {
1099 foreach my $target (@imm22_targets) {
1100 &gen_bpcc($inst, $inst_group, $annul, 0, 0, $cc_combo, $target, $taken, $th_id);
1101 }
1102 }
1103 }
1104 }
1105 }
1106}
1107
1108sub gen_all_bpcc() {
1109 my ($th_id, $inst, $inst_group) = @_;
1110
1111 foreach my $taken (0..1) {
1112 my @cc = (0,2);
1113 @cc = (1,3) if($opt{illinst});
1114 foreach my $which_cc (@cc) {
1115 my @cc_combo_range = (0..15);
1116 foreach my $cc_combo (@cc_combo_range) {
1117 my $setup_ok = &setup_cc_for_bpcc($inst, $inst_group, $taken, $which_cc, $cc_combo, $th_id);
1118 if($setup_ok) {
1119 foreach my $ptn (0..1) {
1120 foreach my $annul (0..1) {
1121 foreach my $target (@imm19_targets) {
1122 &gen_bpcc($inst, $inst_group, $annul, $ptn, $which_cc, $cc_combo, $target, $taken, $th_id);
1123 }
1124 }
1125 }
1126 }
1127 }
1128 }
1129 }
1130}
1131
1132sub gen_bpcc() {
1133 my ($inst, $inst_group, $annul, $ptn, $which_cc, $cc_combo, $target, $taken, $th_id) = @_;
1134
1135 my %bpcc_cond = (
1136 ba => 0x8, bn => 0x0, bne => 0x9, be => 0x1, bg => 0xa,
1137 ble => 0x2, bge => 0xb, bl => 0x3, bgu => 0xc, bleu => 0x4,
1138 bcc => 0xd, bcs => 0x5, bpos => 0xe, bneg => 0x6, bvc => 0xf,
1139 bvs => 0x7
1140 );
1141
1142 return if(($taken == 0) && ($opt{illinst} == 0) && ($inst eq "ba"));
1143 return if(($taken == 1) && ($opt{illinst} == 0) && ($inst eq "bn"));
1144
1145 my $target_limit = 0x200000;
1146 $target_limit = 0x40000 if($inst_group eq "bpcc");
1147
1148 if($taken && ($opt{illinst} == 0) && $target == 0) {
1149 #taken branch on self will be inf-loop
1150 }
1151 else {
1152 if($target & $target_limit) {
1153 printf("setx th%d_nxt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x, %%g2, %%g3\n", $th_id, $inst, $which_cc, $cc_combo,
1154 $ptn, $annul, $taken, $target);
1155 printf("th%d_tgt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target);
1156 printf("jmp %%g3\n");
1157 printf("nop\n");
1158 }
1159
1160 printf("th%d_nxt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target);
1161 printf("th%d_tgt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target) if($target == 0);
1162 if($target & $target_limit) {
1163 printf("add %%g3, 0xc, %%g3\n");
1164 }
1165 if($opt{illinst}) {
1166 my $inst_word = (($annul & 0x1)<<29) | (($bpcc_cond{$inst} & 0xf)<<25) | (0x1<<22) | (($which_cc & 0x3)<<20) |
1167 (($ptn & 0x1)<<19) | ($target & 0x7ffff);
1168 printf(".word 0x%x\n", $inst_word);
1169 }
1170 else {
1171 printf("%s", $inst);
1172 printf(",a") if($annul);
1173 printf(",pt") if($ptn == 1 && ($inst_group eq "bpcc"));
1174 printf(",pn") if($ptn == 0 && ($inst_group eq "bpcc"));
1175 if($inst_group eq "bpcc") {
1176 printf(" %%icc, ") if($which_cc == 0);
1177 printf(" %%xcc, ") if($which_cc == 2);
1178 }
1179 printf(" th%d_tgt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target);
1180 }
1181 if($target == 1) {
1182 printf("th%d_tgt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target);
1183 printf("nop ! delay slot & branch target\n");
1184 printf("\n");
1185 }
1186 else {
1187 if(($inst eq "ba" || $inst eq "bn") && $annul && ($opt{illinst} == 0)) {
1188 #eat annuled instr(make it illegal)
1189 printf(".word 0x0\n");
1190 }
1191 elsif(($taken == 0) && $annul && ($opt{illinst} == 0)) {
1192 #eat annuled instr(make it illegal)
1193 printf(".word 0x0\n");
1194 }
1195 else {
1196 printf("nop ! delay slot\n");
1197 }
1198 if(($target != 0) && (($target & $target_limit) == 0)) {
1199 if(($target > 2) && (($taken == 0) || $opt{illinst})) {
1200 printf("call th%d_tgt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target);
1201 printf("nop\n");
1202 printf(".skip %d\n", ($target-4)*4) if($target > 4);
1203 }
1204 else {
1205 printf(".skip %d\n", ($target-2)*4) if($target > 2);
1206 }
1207 printf("th%d_tgt_%s_cc%x_combo%x_ptn%x_a%x_t%x_tgt%x:\n", $th_id, $inst, $which_cc, $cc_combo, $ptn, $annul, $taken, $target);
1208 printf("nop ! branch target\n");
1209 }
1210 printf("\n");
1211 }
1212 }
1213}
1214
1215sub setup_cc_for_bpcc() {
1216 my ($inst, $inst_group, $taken, $which_cc, $cc_combo, $th_id) = @_;
1217
1218 my $ext_on = 0;
1219 $ext_on = 1 if($inst_group eq "bpcc");
1220
1221 my $cc = $cc_combo;
1222 my $cc_C = ($cc_combo & 0x1);
1223 my $cc_V = ($cc_combo & 0x2)>>1;
1224 my $cc_Z = ($cc_combo & 0x4)>>2;
1225 my $cc_N = ($cc_combo & 0x8)>>3;
1226
1227 if($inst eq "ba" || $inst eq "bn") {
1228 # all cc combos are ok
1229 }
1230 elsif($inst eq "bne") {
1231 return 0 if (($taken == 1) && ($cc_Z == 1));
1232 return 0 if (($taken == 0) && ($cc_Z == 0));
1233 }
1234 elsif($inst eq "be") {
1235 return 0 if (($taken == 1) && ($cc_Z == 0));
1236 return 0 if (($taken == 0) && ($cc_Z == 1));
1237 }
1238 elsif($inst eq "bg") {
1239 return 0 if (($taken == 1) && ( ($cc_Z == 1) ||
1240 (($cc_N == 1) && ($cc_V == 0)) ||
1241 (($cc_N == 0) && ($cc_V == 1)) ) );
1242 return 0 if (($taken == 0) && ( ($cc_Z == 0) &&
1243 (($cc_N == 1) && ($cc_V == 1)) ||
1244 (($cc_N == 0) && ($cc_V == 0)) ) );
1245 }
1246 elsif($inst eq "ble") {
1247 return 0 if (($taken == 1) && ( ($cc_Z == 0) &&
1248 (($cc_N == 1) && ($cc_V == 1)) ||
1249 (($cc_N == 0) && ($cc_V == 0)) ) );
1250 return 0 if (($taken == 0) && ( ($cc_Z == 1) ||
1251 (($cc_N == 1) && ($cc_V == 0)) ||
1252 (($cc_N == 0) && ($cc_V == 1)) ) );
1253 }
1254 elsif($inst eq "bge") {
1255 return 0 if (($taken == 1) && ( (($cc_N == 1) && ($cc_V == 0)) ||
1256 (($cc_N == 0) && ($cc_V == 1)) ) );
1257 return 0 if (($taken == 0) && ( (($cc_N == 1) && ($cc_V == 1)) ||
1258 (($cc_N == 0) && ($cc_V == 0)) ) );
1259 }
1260 elsif($inst eq "bl") {
1261 return 0 if (($taken == 1) && ( (($cc_N == 1) && ($cc_V == 1)) ||
1262 (($cc_N == 0) && ($cc_V == 0)) ) );
1263 return 0 if (($taken == 0) && ( (($cc_N == 1) && ($cc_V == 0)) ||
1264 (($cc_N == 0) && ($cc_V == 1)) ) );
1265 }
1266 elsif($inst eq "bgu") {
1267 return 0 if (($taken == 1) && (($cc_C == 1) || ($cc_Z == 1)));
1268 return 0 if (($taken == 0) && (($cc_C == 0) && ($cc_Z == 0)));
1269 }
1270 elsif($inst eq "bleu") {
1271 return 0 if (($taken == 1) && (($cc_C == 0) && ($cc_Z == 0)));
1272 return 0 if (($taken == 0) && (($cc_C == 1) || ($cc_Z == 1)));
1273 }
1274 elsif($inst eq "bcc") {
1275 return 0 if (($taken == 1) && ($cc_C == 1));
1276 return 0 if (($taken == 0) && ($cc_C == 0));
1277 }
1278 elsif($inst eq "bcs") {
1279 return 0 if (($taken == 1) && ($cc_C == 0));
1280 return 0 if (($taken == 0) && ($cc_C == 1));
1281 }
1282 elsif($inst eq "bpos") {
1283 return 0 if (($taken == 1) && ($cc_N == 1));
1284 return 0 if (($taken == 0) && ($cc_N == 0));
1285 }
1286 elsif($inst eq "bneg") {
1287 return 0 if (($taken == 1) && ($cc_N == 0));
1288 return 0 if (($taken == 0) && ($cc_N == 1));
1289 }
1290 elsif($inst eq "bvc") {
1291 return 0 if (($taken == 1) && ($cc_V == 1));
1292 return 0 if (($taken == 0) && ($cc_V == 0));
1293 }
1294 elsif($inst eq "bvs") {
1295 return 0 if (($taken == 1) && ($cc_V == 0));
1296 return 0 if (($taken == 0) && ($cc_V == 1));
1297 }
1298 else {
1299 printf("ERROR: unknown instruction\n");
1300 }
1301
1302 if($which_cc == 0 || $which_cc == 1) {
1303 &setup_cc($ext_on, ((~$cc)&0xf), $cc, $th_id);
1304 }
1305 if($which_cc == 2 || $which_cc == 3) {
1306 &setup_cc($ext_on, $cc, ((~$cc)&0xf), $th_id);
1307 }
1308 return 1;
1309}
1310
1311sub setup_cc() {
1312 my ($ext_on, $xcc, $icc, $th_id) = @_;
1313
1314 my $value = ($xcc<<4) | $icc;
1315
1316 printf("wr %%g0, 0x%x, %%ccr\n", $value);
1317}
1318
1319my @asi_lda_insts = ("ldsba", "ldsha", "ldswa", "lduba", "lduha", "lduwa",
1320 "ldxa", "ldda", "ldaf", "lddaf", "ldqaf", "prefetcha");
1321
1322my @asi_sta_insts = ("stba", "stha", "stwa", "stxa", "stda",
1323 "staf", "stdaf", "stqaf", "casa", "casxa", "ldstuba", "swapa");
1324
1325my $big_va = Math::BigInt->new(0xc0);
1326$big_va <<=32;
1327#my @asi_va_addrs = (0x0);
1328my @asi_va_addrs = (0x0, $big_va);
1329
1330my %asi_spc_traps = (
1331 0x15 => ("P:casa:dataacc,P:casxa:dataacc"), # Real_IO
1332 0x1d => ("P:casa:dataacc,P:casxa:dataacc"), # Real_IO_L
1333
1334 0x16 => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_LOAD_P
1335 0x17 => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_LOAD_S
1336 0x1e => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_LOAD_P_L
1337 0x1f => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_LOAD_S_L
1338
1339 0x66 => ("N:stxa:dataacc,N:stdaf:dataacc,N:ldxa:dataacc"), # ICACHE_INSTR
1340 0x67 => ("N:stxa:dataacc,N:stdaf:dataacc,N:ldxa:dataacc"), # ICACHE_TAG
1341
1342 0x24 => ("N:ldda:dataacc"), # QUAD_LDDA
1343 0x26 => ("N:ldda:dataacc"), # QUAD_LDDA
1344 0x2c => ("N:ldda:dataacc"), # QUAD_LDDA
1345 0x2e => ("N:ldda:dataacc"), # QUAD_LDDA
1346
1347 0x45 => ("N:stxa:dataacc,N:ldxa:dataacc"), # LSU_CTL
1348 0x4c => ("N:stxa:dataacc,N:ldxa:dataacc"), # SPARC_ERROR_STATUS
1349
1350 0x22 => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1351 0x23 => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1352 0x2a => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1353 0x2b => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1354 0xe2 => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1355 0xe3 => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1356 0xea => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1357 0xeb => ("N:stba:dataacc,N:stha:dataacc,N:stwa:dataacc,N:stxa:dataacc,N:stda:dataacc,N:ldda:dataacc"), # BLK_INIT
1358
1359 0x82 => ("P:stba:dataacc,P:stha:dataacc,P:stwa:dataacc,P:stxa:dataacc,P:stda:dataacc,P:staf:dataacc," .
1360 "P:stdaf:dataacc,P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # NFO
1361 0x83 => ("P:stba:dataacc,P:stha:dataacc,P:stwa:dataacc,P:stxa:dataacc,P:stda:dataacc,P:staf:dataacc," .
1362 "P:stdaf:dataacc,P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # NFO
1363 0x8a => ("P:stba:dataacc,P:stha:dataacc,P:stwa:dataacc,P:stxa:dataacc,P:stda:dataacc,P:staf:dataacc," .
1364 "P:stdaf:dataacc,P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # NFO
1365 0x8b => ("P:stba:dataacc,P:stha:dataacc,P:stwa:dataacc,P:stxa:dataacc,P:stda:dataacc,P:staf:dataacc," .
1366 "P:stdaf:dataacc,P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # NFO
1367
1368 0xf0 => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_P
1369 0xf1 => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_S
1370 0xf8 => ("N:stdaf:dataacc,N:lddaf:dataacc"), # BLK_PL
1371 0xf9 => ("N:stdaf:dataacc,N:lddaf:dataacc") # BLK_SL
1372 );
1373
1374my %asi_io_space_traps = (
1375 0x4 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIN
1376 0xc => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIN
1377 0x10 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1378 0x11 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUS
1379 0x18 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1380 0x19 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUS
1381 0x2a => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1382 0x2b => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUS
1383 0x14 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # REAL_MEM
1384 0x1c => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1385 0x80 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1386 0x81 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1387 0x82 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1388 0x83 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1389 0x88 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1390 0x89 => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1391 0x8a => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc"), # AIUP
1392 0x8b => ("P:casa:dataacc,P:casxa:dataacc,P:ldstuba:dataacc,P:swapa:dataacc") # AIUP
1393 );
1394
1395my %asi_rbw = (
1396 0x42 => ("stxa,stdaf"), # ASI_BIST_CONTROL
1397 0x43 => ("stxa,stdaf"), # ASI_ERR_INJECT
1398 0x44 => ("stxa,stdaf"), # ASI_STRM_CTL
1399 0x73 => ("stxa,stdaf"), # ASI_SWVR_UDB_INTR_W
1400 0x45 => ("stxa,stdaf") # ASI_LSU_CTL_REG
1401 );
1402
1403my %store_rbw_inst = (
1404 stxa => "ldxa",
1405 stdaf => "ldda"
1406 );
1407
1408my %trap_decode = (
1409 illinst => 0x10,
1410 dataacc => 0x16
1411 );
1412
1413my %external_asi = (
1414 0x4 => 1, 0xc => 1, 0x10 => 1, 0x11 => 1, 0x18 => 1, 0x19 => 1,
1415 0x80 => 1, 0x81 => 1, 0x82 => 1, 0x83 => 1, 0x88 => 1, 0x89 => 1, 0x8a => 1, 0x8b => 1,
1416 0x14 => 1, 0x15 => 1, 0x16 => 1, 0x17 => 1, 0x1c => 1, 0x1d => 1, 0x1e => 1, 0x1f => 1,
1417 0x22 => 1, 0x23 => 1, 0x24 => 1, 0x26 => 1, 0x27 => 1, 0x2a => 1, 0x2b => 1, 0x2c => 1,
1418 0x2e => 1, 0x2f => 1, 0xe2 => 1, 0xe3 => 1, 0xea => 1, 0xeb => 1, 0xf0 => 1, 0xf1 => 1,
1419 0xf8 => 1, 0xf9 => 1
1420 );
1421
1422
1423sub read_before_write() {
1424 my ($asi, $inst) = @_;
1425 my ($rbw_inst);
1426 if($opt{hyper} || ($opt{super} && $opt{enboff})) {
1427 }
1428 else {
1429 return 0;
1430 }
1431 foreach my $rbw (split(/,/, $asi_rbw{$asi})) {
1432 ($rbw_inst) = split(/:/, $rbw);
1433 if($rbw_inst eq $inst) {
1434 return 1;
1435 }
1436 }
1437 return 0;
1438}
1439
1440sub enable_trap() {
1441 my ($asi, $inst) = @_;
1442 my $neg_dec_vld = 1;
1443 my ($pos,$trap_inst,$trap_type);
1444 foreach my $traps (split(/,/, $asi_spc_traps{$asi})) {
1445 ($pos,$trap_inst,$trap_type) = split(/:/, $traps);
1446 if($pos eq "P") {
1447 if($trap_inst eq $inst) {
1448 &enable_trap_type($trap_type);
1449 return 1;
1450 }
1451 }
1452 else {
1453 if($trap_inst eq $inst) {
1454 $neg_dec_vld = 0;
1455 }
1456 }
1457 }
1458 if($pos eq "N" && $neg_dec_vld) {
1459 &enable_trap_type($trap_type);
1460 return 1;
1461 }
1462 return 0;
1463}
1464
1465
1466sub enable_io_space_traps() {
1467 my ($asi, $inst) = @_;
1468 my $neg_dec_vld = 1;
1469 my ($pos,$trap_inst,$trap_type);
1470
1471 foreach my $traps (split(/,/, $asi_io_space_traps{$asi})) {
1472 ($pos,$trap_inst,$trap_type) = split(/:/, $traps);
1473 if($pos eq "P") {
1474 if($trap_inst eq $inst) {
1475 &enable_trap_type($trap_type);
1476 return 1;
1477 }
1478 }
1479 else {
1480 if($trap_inst eq $inst) {
1481 $neg_dec_vld = 0;
1482 }
1483 }
1484 }
1485 if($pos eq "N" && $neg_dec_vld) {
1486 &enable_trap_type($trap_type);
1487 return 1;
1488 }
1489 return 0;
1490
1491}
1492
1493sub enable_trap_type() {
1494 my ($trap) = @_;
1495 printf("set 0x%x, %%o0\n", $trap_decode{$trap});
1496 printf("set 0xff, %%o1\n");
1497 if($opt{enboff}) {
1498 printf("ta T_TRAP_EN_N_TIMES\n");
1499 }
1500 else {
1501 printf("ta T_HTRAP_EN_N_TIMES\n");
1502 }
1503}
1504
1505sub gen_all_asi_insts() {
1506 my ($th_id, $asi_str) = @_;
1507 my $asi = hex($asi_str);
1508
1509 &lock_regs(16);
1510 my $tmp1 = &pick_tmp_reg();
1511 my $tmp2 = &pick_tmp_reg();
1512 my $tmp3 = &pick_tmp_reg();
1513
1514 &setx_label("scratch_mem", $tmp1, $tmp2);
1515 printf("ldx [%%r%d+%d], %%r16\n", $tmp2, ($th_id*2*64));
1516 printf("ldx [%%r%d+%d], %%r17\n", $tmp2, ($th_id*2*64)+8);
1517 for(my $i=0; $i<8; $i++) {
1518 printf("ldd [%%r%d+%d], %%f%d\n", $tmp2, ((($th_id*2)+1)*64+($i*8)), (16+$i*2));
1519 }
1520 if($asi == 0x4c) {
1521 &setx_label("0xffffffffffffffff", $tmp1, 16);
1522 }
1523
1524 foreach my $va (@asi_va_addrs) {
1525 if($va >> 39) { # this is an io space.
1526 &setx($va, $tmp1, $tmp3);
1527 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
1528 printf("wr %%g0, 0x14, %%asi\n");
1529 printf("stxa %%r16, [%%r%d+%d] %asi\n", $tmp3, ($th_id*2*64));
1530 printf("stxa %%r17, [%%r%d+%d] %asi\n", $tmp3, ($th_id*2*64)+8);
1531 for(my $i=0; $i<8; $i++) {
1532 printf("stda %%f%d, [%%r%d+%d] %asi\n", (16+$i*2), $tmp3, ((($th_id*2)+1)*64+($i*8)));
1533 }
1534 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
1535 }
1536 }
1537
1538 my $va_offset = 0;
1539 $va_offset = ($th_id*2*64) if($external_asi{$asi});
1540
1541 my @asi_modes = ("normal", "redbit_on", "ambit_on", "redbit_on_ambit_on",
1542 "oor_addr", "oor_addr_redbit_on", "oor_addr_ambit_on", "oor_addr_redbit_on_ambit_on",
1543 "dtlb_off", "dtlb_off_redbit_on", "dtlb_off_ambit_on", "dtlb_off_redbit_on_ambit_on",
1544 "oor_addr_dtlb_off", "oor_addr_dtlb_off_redbit_on", "oor_addr_dtlb_off_ambit_on",
1545 "oor_addr_dtlb_off_redbit_on_ambit_on");
1546 #my @asi_modes = ("normal", "redbit_on", "oor_addr", "oor_addr_redbit_on", "dtlb_off", "dtlb_off_redbit_on",
1547 # "oor_addr_dtlb_off", "oor_addr_dtlb_off_redbit_on");
1548 foreach my $asi_mode (@asi_modes) {
1549 if($asi_mode =~ /dtlb_off/) {
1550 printf("mov 0x1, %%o7\n");
1551 printf("ta T_HTRAP_INST0\n");
1552 }
1553 else {
1554 printf("mov 0x2, %%o7\n");
1555 printf("ta T_HTRAP_INST0\n");
1556 }
1557 if($asi_mode =~ /redbit_on/) {
1558 printf("mov 0x8, %%o7\n");
1559 printf("ta T_HTRAP_INST0\n");
1560 }
1561 else {
1562 printf("mov 0x4, %%o7\n");
1563 printf("ta T_HTRAP_INST0\n");
1564 }
1565 if($asi_mode =~ /ambit_on/) {
1566 printf("!turn on AM bit\n");
1567 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
1568 printf("rdpr %%pstate, %%r%d\n", $tmp1);
1569 printf("or %%r%d, 0x8, %%r%d\n", $tmp1, $tmp1);
1570 printf("wrpr %%r%d, 0x0, %%pstate\n", $tmp1);
1571 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
1572 }
1573 else {
1574 printf("!turn off AM bit\n");
1575 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
1576 printf("rdpr %%pstate, %%r%d\n", $tmp1);
1577 printf("or %%r%d, 0x8, %%r%d\n", $tmp1, $tmp1);
1578 printf("wrpr %%r%d, 0x8, %%pstate\n", $tmp1);
1579 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
1580 }
1581 my $oor_va = 0x0;
1582 if($asi_mode =~ /oor_addr/) {
1583 $oor_va = Math::BigInt->new(0x10000);
1584 $oor_va <<=32;
1585 }
1586 foreach my $va (@asi_va_addrs) {
1587 &setx($va|$oor_va, $tmp2, $tmp1);
1588 foreach my $stinst (@asi_sta_insts) {
1589 my $trap_enabled = 0;
1590 if($stinst eq "stqaf") {
1591 $trap_enabled = &enable_trap_type("illinst");
1592 }
1593 else {
1594 $trap_enabled = &enable_trap($asi, $stinst) if($opt{seltrap});
1595 }
1596 if($trap_enabled == 0 && (($va>>39)&0x1)) {
1597 $trap_enabled = &enable_io_space_traps($asi, $stinst);
1598 }
1599 if($external_asi{$asi} == undef && $stinst eq "stdaf") {
1600 #skip this HACK
1601 }
1602 else {
1603 my $inst = $stinst;
1604 my $src_type = "%r";
1605 $src_type = "%f" if($stinst eq "staf" || $stinst eq "stdaf" || $stinst eq "stqaf");
1606 $src_type = "" if($stinst eq "prefetcha");
1607 $inst =~ s/(.*)f$/$1/g if($stinst eq "staf" || $stinst eq "stdaf" || $stinst eq "stqaf");
1608
1609 if($inst eq "casa" || $inst eq "casxa") {
1610 &cas_alt($inst, $tmp1, 16, $va_offset, $asi, $src_type, 16);
1611 }
1612 elsif($inst eq "ldstuba" || $inst eq "swapa") {
1613 &load_alt($inst, $tmp1, 0, $va_offset, $asi, $src_type, 16);
1614 }
1615 else {
1616 &load_alt($store_rbw_inst{$stinst}, $tmp1, 0, $va_offset, $asi, $src_type, 16) if(&read_before_write($asi, $stinst));
1617 &store_alt($inst, $src_type, 16, $tmp1, 0, $va_offset, $asi);
1618 }
1619 } #end HACK
1620 }
1621 }
1622 foreach my $va (@asi_va_addrs) {
1623 &setx($va|$oor_va, $tmp2, $tmp1);
1624 foreach my $ldinst (@asi_lda_insts) {
1625 if($ldinst eq "ldqaf") {
1626 &enable_trap_type("illinst");
1627 }
1628 else {
1629 &enable_trap($asi, $ldinst);
1630 }
1631 if($external_asi{$asi} == undef && $ldinst eq "lddaf") {
1632 #skip this HACK
1633 }
1634 else {
1635 my $inst = $ldinst;
1636 my $dest_type = "%r";
1637 $dest_type = "%f" if($ldinst eq "ldaf" || $ldinst eq "lddaf" || $ldinst eq "ldqaf");
1638 $dest_type = "" if($ldinst eq "prefetcha");
1639 $inst =~ s/(.*)f$/$1/g if($ldinst eq "ldaf" || $ldinst eq "lddaf" || $ldinst eq "ldqaf");
1640 &load_alt($inst, $tmp1, 0, $va_offset, $asi, $dest_type, 16);
1641 } #end HACK
1642 }
1643 }
1644 }
1645 &release_regs(16,$tmp1,$tmp2,$tmp3);
1646}
1647
1648sub gen_required_data_sections() {
1649 if($opt{inst_group} eq "asi" || $opt{inst_group} eq "ldst") {
1650 foreach my $va (@asi_va_addrs) {
1651 &gen_data_sec($va, $va+1024, $opt{dataacc}, $opt{super}) if($va != 0x0);
1652 }
1653 }
1654}
1655
1656sub hyp_helper_apis() {
1657 my ($tmp1, $tmp2) = (1,2);
1658 printf("SECTION .HTRAPS\n");
1659 printf(".text\n");
1660 printf(".global hyp_api\n");
1661 printf("hyp_api:\n");
1662 printf("and %%o7, 0x1, %%o6\n");
1663 printf("brnz %%o6, turnoff_dtlb\n");
1664 printf("nop\n");
1665 printf("and %%o7, 0x2, %%o6\n");
1666 printf("brnz %%o6, turnon_dtlb\n");
1667 printf("nop\n");
1668 printf("and %%o7, 0x4, %%o6\n");
1669 printf("brnz %%o6, turnoff_redbit\n");
1670 printf("nop\n");
1671 printf("and %%o7, 0x8, %%o6\n");
1672 printf("brnz %%o6, turnon_redbit\n");
1673 printf("nop\n");
1674 printf("ba api_done\n");
1675 printf("nop\n");
1676
1677 printf("turnoff_dtlb:\n");
1678 printf("ldxa [%%g0] 0x45, %%r%d\n", $tmp1);
1679 printf("sllx %%r%d, 60, %%r%d\n", $tmp1, $tmp2);
1680 printf("srlx %%r%d, 63, %%r%d\n", $tmp2, $tmp2);
1681 printf("sllx %%r%d, 3, %%r%d\n", $tmp2, $tmp2);
1682 printf("xor %%r%d, %%r%d, %%r%d\n", $tmp1, $tmp2, $tmp1);
1683 printf("stxa %%r%d, [%%g0] 0x45\n", $tmp1);
1684 printf("ba api_done\n");
1685 printf("nop\n");
1686
1687 printf("turnon_dtlb:\n");
1688 printf("ldxa [%%g0] 0x45, %%r%d\n", $tmp1);
1689 printf("or %%r%d, 0x8, %%r%d\n", $tmp1, $tmp1);
1690 printf("stxa %%r%d, [%%g0] 0x45\n", $tmp1);
1691 printf("ba api_done\n");
1692 printf("nop\n");
1693
1694 printf("turnon_redbit:\n");
1695 printf("rdhpr %%hpstate, %%r%d\n", $tmp1);
1696 printf("or %%r%d, 0x20, %%r%d\n", $tmp1, $tmp1);
1697 printf("wrhpr %%r%d, 0x0, %%hpstate\n", $tmp1);
1698 printf("ba api_done\n");
1699 printf("nop\n");
1700
1701 printf("turnoff_redbit:\n");
1702 printf("rdhpr %%hpstate, %%r%d\n", $tmp1);
1703 printf("sllx %%r%d, 58, %%r%d\n", $tmp1, $tmp2);
1704 printf("srlx %%r%d, 63, %%r%d\n", $tmp2, $tmp2);
1705 printf("sllx %%r%d, 5, %%r%d\n", $tmp2, $tmp2);
1706 printf("wrhpr %%r%d, %%r%d, %%hpstate\n", $tmp1, $tmp2);
1707 printf("ba api_done\n");
1708 printf("nop\n");
1709
1710 printf("api_done:\n");
1711 printf("done\n");
1712}
1713
1714
1715my @asi_ld_insts = ("ldsb", "ldsh", "ldsw", "ldub", "lduh", "lduw",
1716 "ldx", "ldd", "ldf", "lddf", "ldqf", "prefetch");
1717
1718my @asi_st_insts = ("stb", "sth", "stw", "stx", "std",
1719 "stf", "stdf", "stqf", "cas", "casx", "ldstub", "swap");
1720
1721sub gen_all_ldst_insts() {
1722 my ($th_id) = @_;
1723
1724 &lock_regs(16);
1725 my $tmp1 = &pick_tmp_reg();
1726 my $tmp2 = &pick_tmp_reg();
1727 my $tmp3 = &pick_tmp_reg();
1728
1729 &setx_label("scratch_mem", $tmp1, $tmp2);
1730 printf("ldx [%%r%d+%d], %%r16\n", $tmp2, ($th_id*2*64));
1731 printf("ldx [%%r%d+%d], %%r17\n", $tmp2, ($th_id*2*64)+8);
1732 for(my $i=0; $i<8; $i++) {
1733 printf("ldd [%%r%d+%d], %%f%d\n", $tmp2, ((($th_id*2)+1)*64+($i*8)), (16+$i*2));
1734 }
1735
1736 foreach my $va (@asi_va_addrs) {
1737 if($va >> 39) { # this is an io space.
1738 &setx($va, $tmp1, $tmp3);
1739 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
1740 printf("wr %%g0, 0x14, %%asi\n");
1741 printf("stxa %%r16, [%%r%d+%d] %asi\n", $tmp3, ($th_id*2*64));
1742 printf("stxa %%r17, [%%r%d+%d] %asi\n", $tmp3, ($th_id*2*64)+8);
1743 for(my $i=0; $i<8; $i++) {
1744 printf("stda %%f%d, [%%r%d+%d] %asi\n", (16+$i*2), $tmp3, ((($th_id*2)+1)*64+($i*8)));
1745 }
1746 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
1747 }
1748 }
1749
1750 my $va_offset = ($th_id*2*64);
1751
1752 my @asi_modes = ("normal", "redbit_on", "ambit_on", "redbit_on_ambit_on",
1753 "oor_addr", "oor_addr_redbit_on", "oor_addr_ambit_on", "oor_addr_redbit_on_ambit_on",
1754 "dtlb_off", "dtlb_off_redbit_on", "dtlb_off_ambit_on", "dtlb_off_redbit_on_ambit_on",
1755 "oor_addr_dtlb_off", "oor_addr_dtlb_off_redbit_on", "oor_addr_dtlb_off_ambit_on",
1756 "oor_addr_dtlb_off_redbit_on_ambit_on");
1757 #my @asi_modes = ("normal", "redbit_on", "oor_addr", "oor_addr_redbit_on", "dtlb_off", "dtlb_off_redbit_on",
1758 # "oor_addr_dtlb_off", "oor_addr_dtlb_off_redbit_on");
1759 foreach my $asi_mode (@asi_modes) {
1760 if($asi_mode =~ /dtlb_off/) {
1761 printf("mov 0x1, %%o7\n");
1762 printf("ta T_HTRAP_INST0\n");
1763 }
1764 else {
1765 printf("mov 0x2, %%o7\n");
1766 printf("ta T_HTRAP_INST0\n");
1767 }
1768 if($asi_mode =~ /redbit_on/) {
1769 printf("mov 0x8, %%o7\n");
1770 printf("ta T_HTRAP_INST0\n");
1771 }
1772 else {
1773 printf("mov 0x4, %%o7\n");
1774 printf("ta T_HTRAP_INST0\n");
1775 }
1776 if($asi_mode =~ /ambit_on/) {
1777 printf("!turn on AM bit\n");
1778 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
1779 printf("rdpr %%pstate, %%r%d\n", $tmp1);
1780 printf("or %%r%d, 0x8, %%r%d\n", $tmp1, $tmp1);
1781 printf("wrpr %%r%d, 0x0, %%pstate\n", $tmp1);
1782 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
1783 }
1784 else {
1785 printf("!turn off AM bit\n");
1786 printf("ta T_CHANGE_PRIV\n") if($opt{super} == 0);
1787 printf("rdpr %%pstate, %%r%d\n", $tmp1);
1788 printf("or %%r%d, 0x8, %%r%d\n", $tmp1, $tmp1);
1789 printf("wrpr %%r%d, 0x8, %%pstate\n", $tmp1);
1790 printf("ta T_CHANGE_NONPRIV\n") if($opt{super} == 0);
1791 }
1792 my $oor_va = 0x0;
1793 if($asi_mode =~ /oor_addr/) {
1794 $oor_va = Math::BigInt->new(0x10000);
1795 $oor_va <<=32;
1796 }
1797 foreach my $va (@asi_va_addrs) {
1798 &setx($va|$oor_va, $tmp2, $tmp1);
1799 foreach my $stinst (@asi_st_insts) {
1800 my $trap_enabled = 0;
1801 if($stinst eq "stqf") {
1802 $trap_enabled = &enable_trap_type("illinst");
1803 }
1804 if($trap_enabled == 0 && (($va>>39)&0x1)) {
1805 if($stinst eq "cas" || $stinst eq "casx" ||
1806 $stinst eq "ldstub" || $stinst eq "swap") {
1807 $trap_enabled = &enable_trap_type("dataacc");
1808 }
1809 }
1810 my $inst = $stinst;
1811 my $src_type = "%r";
1812 $src_type = "%f" if($stinst eq "stf" || $stinst eq "stdf" || $stinst eq "stqf");
1813 $src_type = "" if($stinst eq "prefetch");
1814 $inst =~ s/(.*)f$/$1/g if($stinst eq "stf" || $stinst eq "stdf" || $stinst eq "stqf");
1815
1816 if($inst eq "cas" || $inst eq "casx") {
1817 &cas($inst, $tmp1, 16, $va_offset, $src_type, 16);
1818 }
1819 elsif($inst eq "ldstub" || $inst eq "swap") {
1820 &load($inst, $tmp1, 0, $va_offset, $src_type, 16);
1821 }
1822 else {
1823 &store($inst, $src_type, 16, $tmp1, 0, $va_offset);
1824 }
1825 }
1826 }
1827 foreach my $va (@asi_va_addrs) {
1828 &setx($va|$oor_va, $tmp2, $tmp1);
1829 foreach my $ldinst (@asi_ld_insts) {
1830 if($ldinst eq "ldqf") {
1831 &enable_trap_type("illinst");
1832 }
1833 my $inst = $ldinst;
1834 my $dest_type = "%r";
1835 $dest_type = "%f" if($ldinst eq "ldf" || $ldinst eq "lddf" || $ldinst eq "ldqf");
1836 $dest_type = "" if($ldinst eq "prefetch");
1837 $inst =~ s/(.*)f$/$1/g if($ldinst eq "ldf" || $ldinst eq "lddf" || $ldinst eq "ldqf");
1838 &load($inst, $tmp1, 0, $va_offset, $dest_type, 16);
1839 }
1840 }
1841 }
1842 &release_regs(16,$tmp1,$tmp2,$tmp3);
1843}
1844
18451;