1*6415b4caStsutsui /* $NetBSD: boot.c,v 1.7 2008/07/16 14:45:17 tsutsui Exp $ */
204faabf0Stsutsui
304faabf0Stsutsui /*-
404faabf0Stsutsui * Copyright (c) 2004 The NetBSD Foundation, Inc.
504faabf0Stsutsui * All rights reserved.
604faabf0Stsutsui *
704faabf0Stsutsui * This code is derived from software contributed to The NetBSD Foundation
804faabf0Stsutsui * by UCHIYAMA Yasushi.
904faabf0Stsutsui *
1004faabf0Stsutsui * Redistribution and use in source and binary forms, with or without
1104faabf0Stsutsui * modification, are permitted provided that the following conditions
1204faabf0Stsutsui * are met:
1304faabf0Stsutsui * 1. Redistributions of source code must retain the above copyright
1404faabf0Stsutsui * notice, this list of conditions and the following disclaimer.
1504faabf0Stsutsui * 2. Redistributions in binary form must reproduce the above copyright
1604faabf0Stsutsui * notice, this list of conditions and the following disclaimer in the
1704faabf0Stsutsui * documentation and/or other materials provided with the distribution.
1804faabf0Stsutsui *
1904faabf0Stsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2004faabf0Stsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2104faabf0Stsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2204faabf0Stsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2304faabf0Stsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2404faabf0Stsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2504faabf0Stsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2604faabf0Stsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2704faabf0Stsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2804faabf0Stsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2904faabf0Stsutsui * POSSIBILITY OF SUCH DAMAGE.
3004faabf0Stsutsui */
3104faabf0Stsutsui
3204faabf0Stsutsui #include <lib/libsa/stand.h>
3304faabf0Stsutsui #include <lib/libkern/libkern.h>
3404faabf0Stsutsui
3504faabf0Stsutsui #include "local.h"
3604faabf0Stsutsui #include "cmd.h"
3704faabf0Stsutsui #include "common.h"
3804faabf0Stsutsui
3904faabf0Stsutsui #include <machine/sbd.h>
4004faabf0Stsutsui #include <machine/pdinfo.h>
4104faabf0Stsutsui #include <machine/vtoc.h>
4204faabf0Stsutsui
4304faabf0Stsutsui #include "console.h"
4404faabf0Stsutsui
4504faabf0Stsutsui
4604faabf0Stsutsui extern const char bootprog_name[];
4704faabf0Stsutsui extern const char bootprog_rev[];
48*6415b4caStsutsui extern const char bootprog_kernrev[];
4904faabf0Stsutsui
5004faabf0Stsutsui struct cmd_batch_tab cmd_batch_tab[] = {
5104faabf0Stsutsui /* func argc argp... */
5204faabf0Stsutsui #if 0
5304faabf0Stsutsui { cmd_boot, 1, { "mem:", 0, 0, 0, 0, 0, 0 } },
5404faabf0Stsutsui { cmd_boot, 1, { "sd0k:netbsd", 0, 0, 0, 0, 0, 0 } },
5504faabf0Stsutsui { cmd_load_binary, 1, { "0x80001000", 0, 0, 0, 0, 0, 0 } },
5604faabf0Stsutsui { cmd_jump, 2, { "0x80001000", "0x80001000", 0, 0, 0, 0, 0 } },
5704faabf0Stsutsui #endif
5804faabf0Stsutsui { NULL, 0, { 0, 0, 0, 0, 0, 0, 0 } } /* terminate */
5904faabf0Stsutsui };
6004faabf0Stsutsui
6104faabf0Stsutsui struct ipl_args ipl_args;
6204faabf0Stsutsui struct device_capability DEVICE_CAPABILITY;
6304faabf0Stsutsui void set_device_capability(void);
64712239e3Sthorpej bool guess_boot_kernel(char *, size_t, int);
6504faabf0Stsutsui extern int kernel_binary_size;
6604faabf0Stsutsui
6704faabf0Stsutsui void
main(int a0,int v0,int v1)6804faabf0Stsutsui main(int a0, int v0, int v1)
6904faabf0Stsutsui {
7004faabf0Stsutsui extern char edata[], end[];
7104faabf0Stsutsui char boot_kernel[32];
7204faabf0Stsutsui char *args[CMDARG_MAX];
7304faabf0Stsutsui int i;
7404faabf0Stsutsui
7504faabf0Stsutsui memset(edata, 0, end - edata);
7604faabf0Stsutsui /* Save args for chain-boot to iopboot */
7704faabf0Stsutsui ipl_args.a0 = a0;
7804faabf0Stsutsui ipl_args.v0 = v0;
7904faabf0Stsutsui ipl_args.v1 = v1;
8004faabf0Stsutsui
8104faabf0Stsutsui console_init();
8204faabf0Stsutsui
8304faabf0Stsutsui printf("\n");
84*6415b4caStsutsui printf("%s boot, Revision %s (from NetBSD %s)\n",
85*6415b4caStsutsui bootprog_name, bootprog_rev, bootprog_kernrev);
8604faabf0Stsutsui
8704faabf0Stsutsui
8804faabf0Stsutsui /* Inquire IPL activated device */
8904faabf0Stsutsui set_device_capability();
9004faabf0Stsutsui
9104faabf0Stsutsui if (!guess_boot_kernel(boot_kernel, sizeof boot_kernel, 0))
9204faabf0Stsutsui goto prompt;
9304faabf0Stsutsui printf(
9404faabf0Stsutsui ">> Press return to boot now, any other key for boot console.\n");
9504faabf0Stsutsui
9604faabf0Stsutsui for (i = 5000; i >= 0; i--) {
9704faabf0Stsutsui int c;
9804faabf0Stsutsui if (i % 1000 == 0)
9904faabf0Stsutsui printf("booting %s - starting %d\r",
10004faabf0Stsutsui boot_kernel, i / 1000);
10104faabf0Stsutsui if ((c = cnscan()) == -1) {
10204faabf0Stsutsui delay(10);
10304faabf0Stsutsui continue;
10404faabf0Stsutsui }
10504faabf0Stsutsui else if (c == '\r')
10604faabf0Stsutsui break;
10704faabf0Stsutsui else
10804faabf0Stsutsui goto prompt;
10904faabf0Stsutsui }
11004faabf0Stsutsui printf("\n[non-interactive mode]\n");
11104faabf0Stsutsui args[0] = "boot";
11204faabf0Stsutsui args[1] = boot_kernel;
11316ed6645Sthorpej cmd_boot(2, args, false);
11404faabf0Stsutsui prompt:
11504faabf0Stsutsui
11604faabf0Stsutsui printf("\ntype \"help\" for help.\n");
11716ed6645Sthorpej console_cursor(true);
11804faabf0Stsutsui prompt();
11904faabf0Stsutsui /* NOTREACHED */
12004faabf0Stsutsui }
12104faabf0Stsutsui
122712239e3Sthorpej bool
guess_boot_kernel(char * name,size_t len,int pri)12304faabf0Stsutsui guess_boot_kernel(char *name, size_t len, int pri)
12404faabf0Stsutsui {
12504faabf0Stsutsui extern struct vtoc_sector vtoc;
12604faabf0Stsutsui struct ux_partition *partition;
12704faabf0Stsutsui int i, unit;
12804faabf0Stsutsui
12904faabf0Stsutsui if (!DEVICE_CAPABILITY.active)
13016ed6645Sthorpej return false;
13104faabf0Stsutsui
13204faabf0Stsutsui unit = DEVICE_CAPABILITY.booted_unit;
13304faabf0Stsutsui
13404faabf0Stsutsui switch (DEVICE_CAPABILITY.booted_device) {
13504faabf0Stsutsui default:
13616ed6645Sthorpej return false;
13704faabf0Stsutsui case NVSRAM_BOOTDEV_FLOPPYDISK:
13804faabf0Stsutsui strncpy(name, "fd:netbsd", len); /* ustarfs */
13916ed6645Sthorpej return true;
14004faabf0Stsutsui
14104faabf0Stsutsui case NVSRAM_BOOTDEV_HARDDISK:
14204faabf0Stsutsui snprintf(name, len, "sd%d:netbsd", unit); /* ustarfs */
14304faabf0Stsutsui if (!read_vtoc())
14416ed6645Sthorpej return true;
14504faabf0Stsutsui
14604faabf0Stsutsui partition = vtoc.partition;
14704faabf0Stsutsui for (i = 0; i < VTOC_MAXPARTITIONS; i++, partition++) {
14804faabf0Stsutsui if (partition->tag != __VTOC_TAG_BSDFFS)
14904faabf0Stsutsui continue;
15004faabf0Stsutsui /* ffs */
15104faabf0Stsutsui snprintf(name, len, "sd%d%c:netbsd", unit, 'a' + i);
15216ed6645Sthorpej return true;
15304faabf0Stsutsui }
15416ed6645Sthorpej return true;
15504faabf0Stsutsui
15604faabf0Stsutsui case NVSRAM_BOOTDEV_CGMT:
15704faabf0Stsutsui break;
15804faabf0Stsutsui case NVSRAM_BOOTDEV_NETWORK:
15904faabf0Stsutsui /*FALLTHROUGH*/
16004faabf0Stsutsui case NVSRAM_BOOTDEV_NETWORK_T_AND_D:
16104faabf0Stsutsui if (kernel_binary_size) {
16204faabf0Stsutsui strncpy(name, "mem:", len); /* datafs */
16316ed6645Sthorpej return true;
16404faabf0Stsutsui }
16504faabf0Stsutsui if (DEVICE_CAPABILITY.network_enabled) {
16604faabf0Stsutsui strncpy(name, "nfs:netbsd", len); /* nfs */
16716ed6645Sthorpej return true;
16804faabf0Stsutsui }
16904faabf0Stsutsui break;
17004faabf0Stsutsui }
17104faabf0Stsutsui
17216ed6645Sthorpej return false;
17304faabf0Stsutsui }
17404faabf0Stsutsui
17504faabf0Stsutsui int
cmd_info(int argc,char * argp[],int interactive)17604faabf0Stsutsui cmd_info(int argc, char *argp[], int interactive)
17704faabf0Stsutsui {
17804faabf0Stsutsui extern char _ftext[], _etext[], _fdata[], _edata[];
17904faabf0Stsutsui extern char _fbss[], end[];
18004faabf0Stsutsui uint32_t m;
18104faabf0Stsutsui int i, size, total;
18204faabf0Stsutsui struct sbdinfo *sbd = SBD_INFO;
18304faabf0Stsutsui
184*6415b4caStsutsui printf("\n>> %s boot, Revision %s (from NetBSD %s) <<\n",
185*6415b4caStsutsui bootprog_name, bootprog_rev, bootprog_kernrev);
18604faabf0Stsutsui
18704faabf0Stsutsui printf("IPL args: 0x%x 0x%x 0x%x\n", ipl_args.a0, ipl_args.v0,
18804faabf0Stsutsui ipl_args.v1);
18904faabf0Stsutsui printf("\ttext : %p-%p\n\tdata : %p-%p\n\t"
19004faabf0Stsutsui "bss : %p-%p\n\tstack: %p\n\theap : %p\n",
19104faabf0Stsutsui _ftext, _etext, _fdata, _edata,
19204faabf0Stsutsui _fbss, end, _ftext, end);
19304faabf0Stsutsui
19404faabf0Stsutsui m = ipl_args.v1;
19504faabf0Stsutsui total = 0;
19604faabf0Stsutsui printf("Memory Area:\n\t");
19704faabf0Stsutsui for (i = 0; i < 8; i++, m >>= 4) {
19804faabf0Stsutsui size = m & 0xf ? ((m & 0xf) << 4) : 0;
19904faabf0Stsutsui total += size;
20004faabf0Stsutsui if (size)
20104faabf0Stsutsui printf("M%d=%dMB ", i, size);
20204faabf0Stsutsui }
20304faabf0Stsutsui printf(" total %dMB\n", total);
20404faabf0Stsutsui
20504faabf0Stsutsui printf("Board Revision:\n");
20604faabf0Stsutsui printf("\tmachine=0x%x, ", sbd->machine);
20704faabf0Stsutsui printf("model=0x%x\n", sbd->model);
20804faabf0Stsutsui printf("\tpmmu=%d, ", sbd->mmu);
20904faabf0Stsutsui printf("cache=%d, ", sbd->cache);
21004faabf0Stsutsui printf("panel=%d, ", sbd->panel);
21104faabf0Stsutsui printf("fdd=%d\n", sbd->fdd);
21204faabf0Stsutsui printf("\tcpu=%d, fpp=%d, fpa=%d, iop=%d\n",
21304faabf0Stsutsui sbd->cpu, sbd->fpp, sbd->fpa, sbd->iop);
21404faabf0Stsutsui printf("\tclock=%d\n", sbd->clock);
21504faabf0Stsutsui printf("\tipl=%d, cpu_ex=%d, fpp_ex=%d\n",
21604faabf0Stsutsui sbd->ipl, sbd->cpu_ex, sbd->fpp_ex);
21704faabf0Stsutsui printf("\tkbms=%d, sio=%d, battery=%d, scsi=%d\n",
21804faabf0Stsutsui sbd->kbms, sbd->sio, sbd->battery, sbd->scsi);
21904faabf0Stsutsui printf("model name=%s\n", sbd->model_name);
22004faabf0Stsutsui
22104faabf0Stsutsui return 0;
22204faabf0Stsutsui }
22304faabf0Stsutsui
22404faabf0Stsutsui int
cmd_reboot(int argc,char * argp[],int interactive)22504faabf0Stsutsui cmd_reboot(int argc, char *argp[], int interactive)
22604faabf0Stsutsui {
22704faabf0Stsutsui int bootdev = -1;
22804faabf0Stsutsui
22904faabf0Stsutsui if (argc > 1)
23004faabf0Stsutsui bootdev = strtoul(argp[1], 0, 0); /* next boot device. */
23104faabf0Stsutsui if (bootdev != NVSRAM_BOOTDEV_FLOPPYDISK &&
23204faabf0Stsutsui bootdev != NVSRAM_BOOTDEV_HARDDISK &&
23304faabf0Stsutsui bootdev != NVSRAM_BOOTDEV_CGMT &&
23404faabf0Stsutsui bootdev != NVSRAM_BOOTDEV_NETWORK) {
23504faabf0Stsutsui printf("invalid boot device.");
23604faabf0Stsutsui bootdev = -1;
23704faabf0Stsutsui }
23804faabf0Stsutsui
23904faabf0Stsutsui switch (SBD_INFO->machine) {
24004faabf0Stsutsui case MACHINE_TR2A:
24104faabf0Stsutsui if (bootdev != -1)
24204faabf0Stsutsui *(uint8_t *)0xbe493030 = bootdev;
24304faabf0Stsutsui *(volatile uint32_t *)0xbe000064 |= 0x80000000;
24404faabf0Stsutsui *(volatile uint8_t *)0xba000004 = 1;
24504faabf0Stsutsui *(uint8_t *)0xbfbffffc = 255;
24604faabf0Stsutsui break;
24704faabf0Stsutsui case MACHINE_TR2:
24804faabf0Stsutsui if (bootdev != -1)
24904faabf0Stsutsui *(uint8_t *)0xbb023030 = bootdev;
25004faabf0Stsutsui *(volatile uint32_t *)0xbfb00000 |= 0x10;
25104faabf0Stsutsui break;
25204faabf0Stsutsui default:
25304faabf0Stsutsui ROM_MONITOR();
25404faabf0Stsutsui }
25504faabf0Stsutsui
25604faabf0Stsutsui while (/*CONSTCOND*/1)
25704faabf0Stsutsui ;
25804faabf0Stsutsui /* NOTREACHED */
25904faabf0Stsutsui return 0;
26004faabf0Stsutsui }
26104faabf0Stsutsui
26204faabf0Stsutsui void
set_device_capability(void)26304faabf0Stsutsui set_device_capability(void)
26404faabf0Stsutsui {
26504faabf0Stsutsui const char *devname[] = {
26604faabf0Stsutsui "Floppy disk",
26704faabf0Stsutsui "Unknown",
26804faabf0Stsutsui "Hard disk",
26904faabf0Stsutsui "Unknown",
27004faabf0Stsutsui "CGMT",
27104faabf0Stsutsui "Unknown",
27204faabf0Stsutsui "Network",
27304faabf0Stsutsui "Unknown",
27404faabf0Stsutsui "Network T&D"
27504faabf0Stsutsui };
27604faabf0Stsutsui int booted_device, booted_unit, fd_format;
27704faabf0Stsutsui
27804faabf0Stsutsui boot_device(&booted_device, &booted_unit, &fd_format);
27904faabf0Stsutsui if (booted_device > NVSRAM_BOOTDEV_MAX ||
28004faabf0Stsutsui booted_device < NVSRAM_BOOTDEV_MIN) {
28104faabf0Stsutsui printf(
2825d1e8b27Swiz "invalid booted device. NVSRAM information isn't valid\n");
28304faabf0Stsutsui } else {
28404faabf0Stsutsui DEVICE_CAPABILITY.booted_device = booted_device;
28504faabf0Stsutsui }
28604faabf0Stsutsui DEVICE_CAPABILITY.booted_unit = booted_unit;
28704faabf0Stsutsui
28804faabf0Stsutsui switch (SBD_INFO->machine) {
28904faabf0Stsutsui case MACHINE_TR2A:
29016ed6645Sthorpej DEVICE_CAPABILITY.active = true;
29104faabf0Stsutsui /* boot has LANCE driver */
29216ed6645Sthorpej DEVICE_CAPABILITY.network_enabled = true;
29304faabf0Stsutsui break;
29404faabf0Stsutsui case MACHINE_TR2:
29516ed6645Sthorpej DEVICE_CAPABILITY.active = true;
29604faabf0Stsutsui break;
29704faabf0Stsutsui default:
29816ed6645Sthorpej DEVICE_CAPABILITY.active = false;
29904faabf0Stsutsui break;
30004faabf0Stsutsui }
30104faabf0Stsutsui
30216ed6645Sthorpej DEVICE_CAPABILITY.fd_enabled = true; /* always enabled */
30304faabf0Stsutsui
30404faabf0Stsutsui if (DEVICE_CAPABILITY.active) {
30504faabf0Stsutsui /*
30604faabf0Stsutsui * When NETWORK IPL, FD IPL doesn't activate ROM DISK routine.
30704faabf0Stsutsui */
30804faabf0Stsutsui if (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_HARDDISK)
30916ed6645Sthorpej DEVICE_CAPABILITY.disk_enabled = true;
31004faabf0Stsutsui }
31104faabf0Stsutsui
31204faabf0Stsutsui printf("FD[%c] DISK[%c] NETWORK[%c] COMPILED[%c]\n",
31304faabf0Stsutsui DEVICE_CAPABILITY.fd_enabled ? 'x' : '_',
31404faabf0Stsutsui DEVICE_CAPABILITY.disk_enabled ? 'x' : '_',
31504faabf0Stsutsui DEVICE_CAPABILITY.network_enabled ? 'x' : '_',
31604faabf0Stsutsui kernel_binary_size ? 'x' : '_');
31704faabf0Stsutsui
31861373eecStsutsui printf("booted from %s IPL", devname[DEVICE_CAPABILITY.booted_device]);
31904faabf0Stsutsui if ((DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK) ||
32004faabf0Stsutsui (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK_T_AND_D))
32104faabf0Stsutsui {
32204faabf0Stsutsui printf("\n");
32304faabf0Stsutsui } else {
32404faabf0Stsutsui printf(" unit %d\n", DEVICE_CAPABILITY.booted_unit);
32504faabf0Stsutsui }
32604faabf0Stsutsui }
32704faabf0Stsutsui
32804faabf0Stsutsui int
cmd_test(int argc,char * argp[],int interactive)32904faabf0Stsutsui cmd_test(int argc, char *argp[], int interactive)
33004faabf0Stsutsui {
33104faabf0Stsutsui
33204faabf0Stsutsui /* MISC TEST ROUTINE */
33304faabf0Stsutsui extern int fdd_test(void);
33404faabf0Stsutsui fdd_test();
33504faabf0Stsutsui #if 0
33604faabf0Stsutsui int i;
33704faabf0Stsutsui
33804faabf0Stsutsui printf("argc=%d\n", argc);
33904faabf0Stsutsui for (i = 0; i < argc; i++)
34004faabf0Stsutsui printf("[%d] %s\n", i, argp[i]);
34104faabf0Stsutsui #endif
34204faabf0Stsutsui #if 0 /* Recover my 360ADII NVSRAM.. */
34304faabf0Stsutsui uint8_t *p = (uint8_t *)0xbe490000;
34404faabf0Stsutsui uint8_t *q = nvsram_tr2a;
34504faabf0Stsutsui int i;
34604faabf0Stsutsui
34704faabf0Stsutsui for (i = 0; i < sizeof nvsram_tr2a; i++) {
34804faabf0Stsutsui *p = *q;
34904faabf0Stsutsui p += 4;
35004faabf0Stsutsui q += 1;
35104faabf0Stsutsui }
35204faabf0Stsutsui #endif
35304faabf0Stsutsui #if 0 /* ROM PUTC test */
35404faabf0Stsutsui char a[]= "ohayotest!";
35504faabf0Stsutsui int i;
35604faabf0Stsutsui for (i = 0; i < 10; i++)
35704faabf0Stsutsui ROM_PUTC(120 + i * 12, 24 * 10, a[i]);
35804faabf0Stsutsui #endif
35904faabf0Stsutsui #if 0 /* ROM SCSI disk routine test TR2 */
36004faabf0Stsutsui uint8_t buf[512*2];
36104faabf0Stsutsui uint8_t *p;
36204faabf0Stsutsui int i;
36304faabf0Stsutsui
36404faabf0Stsutsui printf("type=%d\n", *(uint8_t *)0xbb023034);
36504faabf0Stsutsui memset(buf, 0, sizeof buf);
36604faabf0Stsutsui p = (uint8_t *)(((uint32_t)buf + 511) & ~511);
36704faabf0Stsutsui i = ROM_DK_READ(0, 0, 1, p);
36804faabf0Stsutsui printf("err=%d\n", i);
36904faabf0Stsutsui for (i = 0; i < 64; i++) {
37004faabf0Stsutsui printf("%x ", p[i]);
37104faabf0Stsutsui if (((i + 1) & 0xf) == 0)
37204faabf0Stsutsui printf("\n");
37304faabf0Stsutsui }
37404faabf0Stsutsui #endif
37504faabf0Stsutsui #if 0
37604faabf0Stsutsui /*XXX failed. */
37704faabf0Stsutsui __asm volatile(
37804faabf0Stsutsui ".set noreorder;"
37904faabf0Stsutsui "li $4, 2;"
38004faabf0Stsutsui "mtc0 $4, $16;" /* Config */
38104faabf0Stsutsui "lui $4, 0xbfc2;"
38204faabf0Stsutsui "jr $4;"
38304faabf0Stsutsui "nop;"
38404faabf0Stsutsui ".set reorder");
38504faabf0Stsutsui /* NOTREACHED */
38604faabf0Stsutsui #endif
38704faabf0Stsutsui #if 0
38804faabf0Stsutsui /* FPU test */
38904faabf0Stsutsui {
39004faabf0Stsutsui int v;
39104faabf0Stsutsui __asm volatile(
39204faabf0Stsutsui ".set noreorder;"
39304faabf0Stsutsui "lui %0, 0x2000;"
39404faabf0Stsutsui "mtc0 %0, $12;" /* Cu1 */
39504faabf0Stsutsui "nop;"
39604faabf0Stsutsui "nop;"
39704faabf0Stsutsui "cfc1 %0, $%1;"
39804faabf0Stsutsui "nop;"
39904faabf0Stsutsui "nop;"
40004faabf0Stsutsui ".set reorder"
40104faabf0Stsutsui : "=r"(v) : "i"(0));
40204faabf0Stsutsui printf("FPUId: %x\n", v);
40304faabf0Stsutsui }
40404faabf0Stsutsui #endif
40504faabf0Stsutsui return 0;
40604faabf0Stsutsui }
407