Commit 8346901560d96edf94b803fd3f94db940ad370b3

Authored by bellard
1 parent b7c7b181

sparc64 fixes (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1514 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -297,7 +297,10 @@ VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8259.o
297 297 endif
298 298 ifeq ($(TARGET_BASE_ARCH), sparc)
299 299 ifeq ($(TARGET_ARCH), sparc64)
300   -VL_OBJS+= sun4u.o m48t08.o magic-load.o slavio_serial.o
  300 +VL_OBJS+= sun4u.o ide.o ne2000.o pckbd.o vga.o
  301 +VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
  302 +VL_OBJS+= cirrus_vga.o parallel.o
  303 +VL_OBJS+= magic-load.o
301 304 else
302 305 VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
303 306 endif
... ...
configure
... ... @@ -153,6 +153,8 @@ for opt do
153 153 ;;
154 154 --cc=*) cc=`echo $opt | cut -d '=' -f 2`
155 155 ;;
  156 + --host-cc=*) host_cc=`echo $opt | cut -d '=' -f 2`
  157 + ;;
156 158 --make=*) make=`echo $opt | cut -d '=' -f 2`
157 159 ;;
158 160 --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
... ... @@ -339,6 +341,7 @@ echo "Advanced options (experts only):"
339 341 echo " --source-path=PATH path of source code [$source_path]"
340 342 echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
341 343 echo " --cc=CC use C compiler CC [$cc]"
  344 +echo " --host-cc=CC use C compiler CC [$cc] for dyngen etc."
342 345 echo " --make=MAKE use specified make [$make]"
343 346 echo " --static enable static build [$static]"
344 347 echo " --enable-mingw32 enable Win32 cross compilation with mingw32"
... ... @@ -420,6 +423,7 @@ echo "ELF interp prefix $interp_prefix"
420 423 fi
421 424 echo "Source path $source_path"
422 425 echo "C compiler $cc"
  426 +echo "Host C compiler $host_cc"
423 427 echo "make $make"
424 428 echo "host CPU $cpu"
425 429 echo "host big endian $bigendian"
... ...
hw/magic-load.c
... ... @@ -139,7 +139,7 @@ int load_elf(const char *filename, uint8_t *addr)
139 139  
140 140 if (find_phdr64(&ehdr64, fd, &phdr, PT_LOAD))
141 141 goto error;
142   - retval = read_program64(fd, &phdr, addr, ehdr64.e_entry);
  142 + retval = read_program64(fd, &phdr, phys_ram_base + ehdr64.e_entry, ehdr64.e_entry);
143 143 if (retval < 0)
144 144 goto error;
145 145 load_symbols64(&ehdr64, fd);
... ...
hw/pci.c
... ... @@ -1291,6 +1291,253 @@ PCIBus *pci_pmac_init(void)
1291 1291 return s;
1292 1292 }
1293 1293  
  1294 +/* Ultrasparc APB PCI host */
  1295 +static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
  1296 + uint32_t val)
  1297 +{
  1298 + PCIBus *s = opaque;
  1299 + int i;
  1300 +
  1301 + for (i = 11; i < 32; i++) {
  1302 + if ((val & (1 << i)) != 0)
  1303 + break;
  1304 + }
  1305 + s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
  1306 +}
  1307 +
  1308 +static uint32_t pci_apb_config_readl (void *opaque,
  1309 + target_phys_addr_t addr)
  1310 +{
  1311 + PCIBus *s = opaque;
  1312 + uint32_t val;
  1313 + int devfn;
  1314 +
  1315 + devfn = (s->config_reg >> 8) & 0xFF;
  1316 + val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
  1317 + return val;
  1318 +}
  1319 +
  1320 +static CPUWriteMemoryFunc *pci_apb_config_write[] = {
  1321 + &pci_apb_config_writel,
  1322 + &pci_apb_config_writel,
  1323 + &pci_apb_config_writel,
  1324 +};
  1325 +
  1326 +static CPUReadMemoryFunc *pci_apb_config_read[] = {
  1327 + &pci_apb_config_readl,
  1328 + &pci_apb_config_readl,
  1329 + &pci_apb_config_readl,
  1330 +};
  1331 +
  1332 +static void apb_config_writel (void *opaque, target_phys_addr_t addr,
  1333 + uint32_t val)
  1334 +{
  1335 + //PCIBus *s = opaque;
  1336 +
  1337 + switch (addr & 0x3f) {
  1338 + case 0x00: // Control/Status
  1339 + case 0x10: // AFSR
  1340 + case 0x18: // AFAR
  1341 + case 0x20: // Diagnostic
  1342 + case 0x28: // Target address space
  1343 + // XXX
  1344 + default:
  1345 + break;
  1346 + }
  1347 +}
  1348 +
  1349 +static uint32_t apb_config_readl (void *opaque,
  1350 + target_phys_addr_t addr)
  1351 +{
  1352 + //PCIBus *s = opaque;
  1353 + uint32_t val;
  1354 +
  1355 + switch (addr & 0x3f) {
  1356 + case 0x00: // Control/Status
  1357 + case 0x10: // AFSR
  1358 + case 0x18: // AFAR
  1359 + case 0x20: // Diagnostic
  1360 + case 0x28: // Target address space
  1361 + // XXX
  1362 + default:
  1363 + val = 0;
  1364 + break;
  1365 + }
  1366 + return val;
  1367 +}
  1368 +
  1369 +static CPUWriteMemoryFunc *apb_config_write[] = {
  1370 + &apb_config_writel,
  1371 + &apb_config_writel,
  1372 + &apb_config_writel,
  1373 +};
  1374 +
  1375 +static CPUReadMemoryFunc *apb_config_read[] = {
  1376 + &apb_config_readl,
  1377 + &apb_config_readl,
  1378 + &apb_config_readl,
  1379 +};
  1380 +
  1381 +static void pci_apb_writeb (void *opaque, target_phys_addr_t addr,
  1382 + uint32_t val)
  1383 +{
  1384 + PCIBus *s = opaque;
  1385 +
  1386 + pci_data_write(s, addr & 7, val, 1);
  1387 +}
  1388 +
  1389 +static void pci_apb_writew (void *opaque, target_phys_addr_t addr,
  1390 + uint32_t val)
  1391 +{
  1392 + PCIBus *s = opaque;
  1393 +
  1394 + pci_data_write(s, addr & 7, val, 2);
  1395 +}
  1396 +
  1397 +static void pci_apb_writel (void *opaque, target_phys_addr_t addr,
  1398 + uint32_t val)
  1399 +{
  1400 + PCIBus *s = opaque;
  1401 +
  1402 + pci_data_write(s, addr & 7, val, 4);
  1403 +}
  1404 +
  1405 +static uint32_t pci_apb_readb (void *opaque, target_phys_addr_t addr)
  1406 +{
  1407 + PCIBus *s = opaque;
  1408 + uint32_t val;
  1409 +
  1410 + val = pci_data_read(s, addr & 7, 1);
  1411 + return val;
  1412 +}
  1413 +
  1414 +static uint32_t pci_apb_readw (void *opaque, target_phys_addr_t addr)
  1415 +{
  1416 + PCIBus *s = opaque;
  1417 + uint32_t val;
  1418 +
  1419 + val = pci_data_read(s, addr & 7, 2);
  1420 + return val;
  1421 +}
  1422 +
  1423 +static uint32_t pci_apb_readl (void *opaque, target_phys_addr_t addr)
  1424 +{
  1425 + PCIBus *s = opaque;
  1426 + uint32_t val;
  1427 +
  1428 + val = pci_data_read(s, addr, 4);
  1429 + return val;
  1430 +}
  1431 +
  1432 +static CPUWriteMemoryFunc *pci_apb_write[] = {
  1433 + &pci_apb_writeb,
  1434 + &pci_apb_writew,
  1435 + &pci_apb_writel,
  1436 +};
  1437 +
  1438 +static CPUReadMemoryFunc *pci_apb_read[] = {
  1439 + &pci_apb_readb,
  1440 + &pci_apb_readw,
  1441 + &pci_apb_readl,
  1442 +};
  1443 +
  1444 +static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
  1445 + uint32_t val)
  1446 +{
  1447 + cpu_outb(NULL, addr & 0xffff, val);
  1448 +}
  1449 +
  1450 +static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
  1451 + uint32_t val)
  1452 +{
  1453 + cpu_outw(NULL, addr & 0xffff, val);
  1454 +}
  1455 +
  1456 +static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
  1457 + uint32_t val)
  1458 +{
  1459 + cpu_outl(NULL, addr & 0xffff, val);
  1460 +}
  1461 +
  1462 +static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
  1463 +{
  1464 + uint32_t val;
  1465 +
  1466 + val = cpu_inb(NULL, addr & 0xffff);
  1467 + return val;
  1468 +}
  1469 +
  1470 +static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
  1471 +{
  1472 + uint32_t val;
  1473 +
  1474 + val = cpu_inw(NULL, addr & 0xffff);
  1475 + return val;
  1476 +}
  1477 +
  1478 +static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
  1479 +{
  1480 + uint32_t val;
  1481 +
  1482 + val = cpu_inl(NULL, addr & 0xffff);
  1483 + return val;
  1484 +}
  1485 +
  1486 +static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
  1487 + &pci_apb_iowriteb,
  1488 + &pci_apb_iowritew,
  1489 + &pci_apb_iowritel,
  1490 +};
  1491 +
  1492 +static CPUReadMemoryFunc *pci_apb_ioread[] = {
  1493 + &pci_apb_ioreadb,
  1494 + &pci_apb_ioreadw,
  1495 + &pci_apb_ioreadl,
  1496 +};
  1497 +
  1498 +PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base)
  1499 +{
  1500 + PCIBus *s;
  1501 + PCIDevice *d;
  1502 + int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
  1503 +
  1504 + /* Ultrasparc APB main bus */
  1505 + s = pci_register_bus();
  1506 + s->set_irq = pci_set_irq_simple;
  1507 +
  1508 + pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
  1509 + pci_apb_config_write, s);
  1510 + apb_config = cpu_register_io_memory(0, apb_config_read,
  1511 + apb_config_write, s);
  1512 + pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
  1513 + pci_apb_write, s);
  1514 + pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
  1515 + pci_apb_iowrite, s);
  1516 +
  1517 + cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
  1518 + cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, pci_mem_config);
  1519 + cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, pci_ioport);
  1520 + cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
  1521 +
  1522 + d = pci_register_device(s, "Advanced PCI Bus", sizeof(PCIDevice),
  1523 + -1, NULL, NULL);
  1524 + d->config[0x00] = 0x8e; // vendor_id : Sun
  1525 + d->config[0x01] = 0x10;
  1526 + d->config[0x02] = 0x00; // device_id
  1527 + d->config[0x03] = 0xa0;
  1528 + d->config[0x04] = 0x06; // command = bus master, pci mem
  1529 + d->config[0x05] = 0x00;
  1530 + d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
  1531 + d->config[0x07] = 0x03; // status = medium devsel
  1532 + d->config[0x08] = 0x00; // revision
  1533 + d->config[0x09] = 0x00; // programming i/f
  1534 + d->config[0x0A] = 0x00; // class_sub = pci host
  1535 + d->config[0x0B] = 0x06; // class_base = PCI_bridge
  1536 + d->config[0x0D] = 0x10; // latency_timer
  1537 + d->config[0x0E] = 0x00; // header_type
  1538 + return s;
  1539 +}
  1540 +
1294 1541 /***********************************************************/
1295 1542 /* generic PCI irq support */
1296 1543  
... ...
hw/sun4u.c
... ... @@ -22,23 +22,18 @@
22 22 * THE SOFTWARE.
23 23 */
24 24 #include "vl.h"
25   -#include "m48t08.h"
  25 +#include "m48t59.h"
26 26  
27   -#define KERNEL_LOAD_ADDR 0x00004000
28   -#define CMDLINE_ADDR 0x007ff000
29   -#define INITRD_LOAD_ADDR 0x00800000
30   -#define PROM_ADDR 0xffd00000
  27 +#define KERNEL_LOAD_ADDR 0x00404000
  28 +#define CMDLINE_ADDR 0x003ff000
  29 +#define INITRD_LOAD_ADDR 0x00300000
  30 +#define PROM_ADDR 0x1fff0000000ULL
  31 +#define APB_SPECIAL_BASE 0x1fe00000000ULL
  32 +#define APB_MEM_BASE 0x1ff00000000ULL
  33 +#define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
31 34 #define PROM_FILENAMEB "proll-sparc64.bin"
32 35 #define PROM_FILENAMEE "proll-sparc64.elf"
33   -#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */
34   -#define PHYS_JJ_IDPROM_OFF 0x1FD8
35   -#define PHYS_JJ_EEPROM_SIZE 0x2000
36   -// IRQs are not PIL ones, but master interrupt controller register
37   -// bits
38   -#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */
39   -#define PHYS_JJ_MS_KBD_IRQ 14
40   -#define PHYS_JJ_SER 0x71100000 /* Serial */
41   -#define PHYS_JJ_SER_IRQ 15
  36 +#define NVRAM_SIZE 0x2000
42 37  
43 38 /* TSC handling */
44 39  
... ... @@ -70,79 +65,170 @@ void DMA_register_channel (int nchan,
70 65 {
71 66 }
72 67  
73   -static void nvram_set_word (m48t08_t *nvram, uint32_t addr, uint16_t value)
  68 +/* NVRAM helpers */
  69 +void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
74 70 {
75   - m48t08_write(nvram, addr++, (value >> 8) & 0xff);
76   - m48t08_write(nvram, addr++, value & 0xff);
  71 + m48t59_set_addr(nvram, addr);
  72 + m48t59_write(nvram, value);
77 73 }
78 74  
79   -static void nvram_set_lword (m48t08_t *nvram, uint32_t addr, uint32_t value)
  75 +uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
80 76 {
81   - m48t08_write(nvram, addr++, value >> 24);
82   - m48t08_write(nvram, addr++, (value >> 16) & 0xff);
83   - m48t08_write(nvram, addr++, (value >> 8) & 0xff);
84   - m48t08_write(nvram, addr++, value & 0xff);
  77 + m48t59_set_addr(nvram, addr);
  78 + return m48t59_read(nvram);
85 79 }
86 80  
87   -static void nvram_set_string (m48t08_t *nvram, uint32_t addr,
  81 +void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
  82 +{
  83 + m48t59_set_addr(nvram, addr);
  84 + m48t59_write(nvram, value >> 8);
  85 + m48t59_set_addr(nvram, addr + 1);
  86 + m48t59_write(nvram, value & 0xFF);
  87 +}
  88 +
  89 +uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
  90 +{
  91 + uint16_t tmp;
  92 +
  93 + m48t59_set_addr(nvram, addr);
  94 + tmp = m48t59_read(nvram) << 8;
  95 + m48t59_set_addr(nvram, addr + 1);
  96 + tmp |= m48t59_read(nvram);
  97 +
  98 + return tmp;
  99 +}
  100 +
  101 +void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
  102 +{
  103 + m48t59_set_addr(nvram, addr);
  104 + m48t59_write(nvram, value >> 24);
  105 + m48t59_set_addr(nvram, addr + 1);
  106 + m48t59_write(nvram, (value >> 16) & 0xFF);
  107 + m48t59_set_addr(nvram, addr + 2);
  108 + m48t59_write(nvram, (value >> 8) & 0xFF);
  109 + m48t59_set_addr(nvram, addr + 3);
  110 + m48t59_write(nvram, value & 0xFF);
  111 +}
  112 +
  113 +uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
  114 +{
  115 + uint32_t tmp;
  116 +
  117 + m48t59_set_addr(nvram, addr);
  118 + tmp = m48t59_read(nvram) << 24;
  119 + m48t59_set_addr(nvram, addr + 1);
  120 + tmp |= m48t59_read(nvram) << 16;
  121 + m48t59_set_addr(nvram, addr + 2);
  122 + tmp |= m48t59_read(nvram) << 8;
  123 + m48t59_set_addr(nvram, addr + 3);
  124 + tmp |= m48t59_read(nvram);
  125 +
  126 + return tmp;
  127 +}
  128 +
  129 +void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
88 130 const unsigned char *str, uint32_t max)
89 131 {
90   - unsigned int i;
  132 + int i;
91 133  
92 134 for (i = 0; i < max && str[i] != '\0'; i++) {
93   - m48t08_write(nvram, addr + i, str[i]);
  135 + m48t59_set_addr(nvram, addr + i);
  136 + m48t59_write(nvram, str[i]);
94 137 }
95   - m48t08_write(nvram, addr + max - 1, '\0');
  138 + m48t59_set_addr(nvram, addr + max - 1);
  139 + m48t59_write(nvram, '\0');
96 140 }
97 141  
98   -static m48t08_t *nvram;
  142 +int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
  143 +{
  144 + int i;
  145 +
  146 + memset(dst, 0, max);
  147 + for (i = 0; i < max; i++) {
  148 + dst[i] = NVRAM_get_byte(nvram, addr + i);
  149 + if (dst[i] == '\0')
  150 + break;
  151 + }
  152 +
  153 + return i;
  154 +}
  155 +
  156 +static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
  157 +{
  158 + uint16_t tmp;
  159 + uint16_t pd, pd1, pd2;
  160 +
  161 + tmp = prev >> 8;
  162 + pd = prev ^ value;
  163 + pd1 = pd & 0x000F;
  164 + pd2 = ((pd >> 4) & 0x000F) ^ pd1;
  165 + tmp ^= (pd1 << 3) | (pd1 << 8);
  166 + tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
  167 +
  168 + return tmp;
  169 +}
  170 +
  171 +uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
  172 +{
  173 + uint32_t i;
  174 + uint16_t crc = 0xFFFF;
  175 + int odd;
  176 +
  177 + odd = count & 1;
  178 + count &= ~1;
  179 + for (i = 0; i != count; i++) {
  180 + crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
  181 + }
  182 + if (odd) {
  183 + crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
  184 + }
  185 +
  186 + return crc;
  187 +}
99 188  
100 189 extern int nographic;
101 190  
102   -static void nvram_init(m48t08_t *nvram, uint8_t *macaddr, const char *cmdline,
103   - int boot_device, uint32_t RAM_size,
104   - uint32_t kernel_size,
105   - int width, int height, int depth)
106   -{
107   - unsigned char tmp = 0;
108   - int i, j;
109   -
110   - // Try to match PPC NVRAM
111   - nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
112   - nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
113   - // NVRAM_size, arch not applicable
114   - m48t08_write(nvram, 0x2F, nographic & 0xff);
115   - nvram_set_lword(nvram, 0x30, RAM_size);
116   - m48t08_write(nvram, 0x34, boot_device & 0xff);
117   - nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
118   - nvram_set_lword(nvram, 0x3C, kernel_size);
  191 +int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
  192 + const unsigned char *arch,
  193 + uint32_t RAM_size, int boot_device,
  194 + uint32_t kernel_image, uint32_t kernel_size,
  195 + const char *cmdline,
  196 + uint32_t initrd_image, uint32_t initrd_size,
  197 + uint32_t NVRAM_image,
  198 + int width, int height, int depth)
  199 +{
  200 + uint16_t crc;
  201 +
  202 + /* Set parameters for Open Hack'Ware BIOS */
  203 + NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
  204 + NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
  205 + NVRAM_set_word(nvram, 0x14, NVRAM_size);
  206 + NVRAM_set_string(nvram, 0x20, arch, 16);
  207 + NVRAM_set_byte(nvram, 0x2f, nographic & 0xff);
  208 + NVRAM_set_lword(nvram, 0x30, RAM_size);
  209 + NVRAM_set_byte(nvram, 0x34, boot_device);
  210 + NVRAM_set_lword(nvram, 0x38, kernel_image);
  211 + NVRAM_set_lword(nvram, 0x3C, kernel_size);
119 212 if (cmdline) {
120   - strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
121   - nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
122   - nvram_set_lword(nvram, 0x44, strlen(cmdline));
  213 + /* XXX: put the cmdline in NVRAM too ? */
  214 + strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
  215 + NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
  216 + NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
  217 + } else {
  218 + NVRAM_set_lword(nvram, 0x40, 0);
  219 + NVRAM_set_lword(nvram, 0x44, 0);
123 220 }
124   - // initrd_image, initrd_size passed differently
125   - nvram_set_word(nvram, 0x54, width);
126   - nvram_set_word(nvram, 0x56, height);
127   - nvram_set_word(nvram, 0x58, depth);
128   -
129   - // Sun4m specific use
130   - i = 0x1fd8;
131   - m48t08_write(nvram, i++, 0x01);
132   - m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */
133   - j = 0;
134   - m48t08_write(nvram, i++, macaddr[j++]);
135   - m48t08_write(nvram, i++, macaddr[j++]);
136   - m48t08_write(nvram, i++, macaddr[j++]);
137   - m48t08_write(nvram, i++, macaddr[j++]);
138   - m48t08_write(nvram, i++, macaddr[j++]);
139   - m48t08_write(nvram, i, macaddr[j]);
140   -
141   - /* Calculate checksum */
142   - for (i = 0x1fd8; i < 0x1fe7; i++) {
143   - tmp ^= m48t08_read(nvram, i);
144   - }
145   - m48t08_write(nvram, 0x1fe7, tmp);
  221 + NVRAM_set_lword(nvram, 0x48, initrd_image);
  222 + NVRAM_set_lword(nvram, 0x4C, initrd_size);
  223 + NVRAM_set_lword(nvram, 0x50, NVRAM_image);
  224 +
  225 + NVRAM_set_word(nvram, 0x54, width);
  226 + NVRAM_set_word(nvram, 0x56, height);
  227 + NVRAM_set_word(nvram, 0x58, depth);
  228 + crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
  229 + NVRAM_set_word(nvram, 0xFC, crc);
  230 +
  231 + return 0;
146 232 }
147 233  
148 234 void pic_info()
... ... @@ -157,21 +243,25 @@ void pic_set_irq(int irq, int level)
157 243 {
158 244 }
159 245  
160   -void vga_update_display()
  246 +void pic_set_irq_new(void *opaque, int irq, int level)
161 247 {
162 248 }
163 249  
164   -void vga_invalidate_display()
  250 +void qemu_system_powerdown(void)
165 251 {
166 252 }
167 253  
168   -void vga_screen_dump(const char *filename)
169   -{
170   -}
  254 +static const int ide_iobase[2] = { 0x1f0, 0x170 };
  255 +static const int ide_iobase2[2] = { 0x3f6, 0x376 };
  256 +static const int ide_irq[2] = { 14, 15 };
171 257  
172   -void qemu_system_powerdown(void)
173   -{
174   -}
  258 +static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
  259 +static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
  260 +
  261 +static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
  262 +static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
  263 +
  264 +static fdctrl_t *floppy_controller;
175 265  
176 266 /* Sun4u hardware initialisation */
177 267 static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
... ... @@ -180,21 +270,18 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
180 270 const char *initrd_filename)
181 271 {
182 272 char buf[1024];
  273 + m48t59_t *nvram;
183 274 int ret, linux_boot;
184 275 unsigned int i;
185   - long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
  276 + long prom_offset, initrd_size, kernel_size;
  277 + PCIBus *pci_bus;
186 278  
187 279 linux_boot = (kernel_filename != NULL);
188 280  
189 281 /* allocate RAM */
190 282 cpu_register_physical_memory(0, ram_size, 0);
191 283  
192   - nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
193   - // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
194   - // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
195   - slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
196   -
197   - prom_offset = ram_size + vram_size;
  284 + prom_offset = ram_size + vga_ram_size;
198 285  
199 286 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
200 287 ret = load_elf(buf, phys_ram_base + prom_offset);
... ... @@ -211,6 +298,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
211 298 prom_offset | IO_MEM_ROM);
212 299  
213 300 kernel_size = 0;
  301 + initrd_size = 0;
214 302 if (linux_boot) {
215 303 kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
216 304 if (kernel_size < 0)
... ... @@ -224,7 +312,6 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
224 312 }
225 313  
226 314 /* load initrd */
227   - initrd_size = 0;
228 315 if (initrd_filename) {
229 316 initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
230 317 if (initrd_size < 0) {
... ... @@ -244,7 +331,41 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
244 331 }
245 332 }
246 333 }
247   - nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth);
  334 + pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE);
  335 + isa_mem_base = VGA_BASE;
  336 + vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
  337 + vga_ram_size, 0, 0);
  338 + cpu_register_physical_memory(VGA_BASE, vga_ram_size, ram_size);
  339 + //pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size);
  340 +
  341 + for(i = 0; i < MAX_SERIAL_PORTS; i++) {
  342 + if (serial_hds[i]) {
  343 + serial_init(serial_io[i], serial_irq[i], serial_hds[i]);
  344 + }
  345 + }
  346 +
  347 + for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
  348 + if (parallel_hds[i]) {
  349 + parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
  350 + }
  351 + }
  352 +
  353 + for(i = 0; i < nb_nics; i++) {
  354 + pci_ne2000_init(pci_bus, &nd_table[i]);
  355 + }
  356 +
  357 + pci_cmd646_ide_init(pci_bus, bs_table, 1);
  358 + kbd_init();
  359 + floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
  360 + nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE);
  361 + sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device,
  362 + KERNEL_LOAD_ADDR, kernel_size,
  363 + kernel_cmdline,
  364 + INITRD_LOAD_ADDR, initrd_size,
  365 + /* XXX: need an option to load a NVRAM image */
  366 + 0,
  367 + graphic_width, graphic_height, graphic_depth);
  368 +
248 369 }
249 370  
250 371 QEMUMachine sun4u_machine = {
... ...
qemu-doc.texi
... ... @@ -1058,6 +1058,19 @@ Set the initial TCX graphic mode. The default is 1024x768.
1058 1058 Use the executable @file{qemu-system-sparc64} to simulate a Sun4u machine.
1059 1059 The emulator is not usable for anything yet.
1060 1060  
  1061 +QEMU emulates the following sun4u peripherals:
  1062 +
  1063 +@itemize @minus
  1064 +@item
  1065 +UltraSparc IIi APB PCI Bridge
  1066 +@item
  1067 +PCI VGA compatible card with VESA Bochs Extensions
  1068 +@item
  1069 +Non Volatile RAM M48T59
  1070 +@item
  1071 +PC-compatible serial ports
  1072 +@end itemize
  1073 +
1061 1074 @chapter MIPS System emulator invocation
1062 1075  
1063 1076 Use the executable @file{qemu-system-mips} to simulate a MIPS machine.
... ...
qemu-tech.texi
... ... @@ -163,7 +163,6 @@ implemented. Floating point exception support is untested.
163 163 @item Atomic instructions are not correctly implemented.
164 164  
165 165 @item Sparc64 emulators are not usable for anything yet.
166   -Address space is limited to first 4 gigabytes.
167 166  
168 167 @end itemize
169 168  
... ...
target-sparc/cpu.h
... ... @@ -6,9 +6,11 @@
6 6 #if !defined(TARGET_SPARC64)
7 7 #define TARGET_LONG_BITS 32
8 8 #define TARGET_FPREGS 32
  9 +#define TARGET_PAGE_BITS 12 /* 4k */
9 10 #else
10 11 #define TARGET_LONG_BITS 64
11 12 #define TARGET_FPREGS 64
  13 +#define TARGET_PAGE_BITS 12 /* XXX */
12 14 #endif
13 15 #define TARGET_FPREG_T float
14 16  
... ... @@ -35,6 +37,7 @@
35 37 #define TT_TRAP 0x80
36 38 #else
37 39 #define TT_TFAULT 0x08
  40 +#define TT_TMISS 0x09
38 41 #define TT_ILL_INSN 0x10
39 42 #define TT_PRIV_INSN 0x11
40 43 #define TT_NFPU_INSN 0x20
... ... @@ -42,6 +45,9 @@
42 45 #define TT_CLRWIN 0x24
43 46 #define TT_DIV_ZERO 0x28
44 47 #define TT_DFAULT 0x30
  48 +#define TT_DMISS 0x31
  49 +#define TT_DPROT 0x32
  50 +#define TT_PRIV_ACT 0x37
45 51 #define TT_EXTINT 0x40
46 52 #define TT_SPILL 0x80
47 53 #define TT_FILL 0xc0
... ... @@ -65,10 +71,14 @@
65 71 #define TBR_BASE_MASK 0xfffff000
66 72  
67 73 #if defined(TARGET_SPARC64)
  74 +#define PS_IG (1<<11)
  75 +#define PS_MG (1<<10)
  76 +#define PS_RED (1<<5)
68 77 #define PS_PEF (1<<4)
69 78 #define PS_AM (1<<3)
70 79 #define PS_PRIV (1<<2)
71 80 #define PS_IE (1<<1)
  81 +#define PS_AG (1<<0)
72 82 #endif
73 83  
74 84 /* Fcc */
... ... @@ -166,7 +176,7 @@ typedef struct CPUSPARCState {
166 176 context) */
167 177 unsigned long mem_write_pc; /* host pc at which the memory was
168 178 written */
169   - unsigned long mem_write_vaddr; /* target virtual addr at which the
  179 + target_ulong mem_write_vaddr; /* target virtual addr at which the
170 180 memory was written */
171 181 /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */
172 182 CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
... ... @@ -201,11 +211,13 @@ typedef struct CPUSPARCState {
201 211 uint32_t pstate;
202 212 uint32_t tl;
203 213 uint32_t cansave, canrestore, otherwin, wstate, cleanwin;
204   - target_ulong agregs[8]; /* alternate general registers */
205   - target_ulong igregs[8]; /* interrupt general registers */
206   - target_ulong mgregs[8]; /* mmu general registers */
  214 + uint64_t agregs[8]; /* alternate general registers */
  215 + uint64_t bgregs[8]; /* backup for normal global registers */
  216 + uint64_t igregs[8]; /* interrupt general registers */
  217 + uint64_t mgregs[8]; /* mmu general registers */
207 218 uint64_t version;
208 219 uint64_t fprs;
  220 + uint64_t tick_cmpr, stick_cmpr;
209 221 #endif
210 222 #if !defined(TARGET_SPARC64) && !defined(reg_T2)
211 223 target_ulong t2;
... ... @@ -275,7 +287,6 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
275 287 struct siginfo;
276 288 int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
277 289  
278   -#define TARGET_PAGE_BITS 12 /* 4k */
279 290 #include "cpu-all.h"
280 291  
281 292 #endif
... ...
target-sparc/exec.h
... ... @@ -65,6 +65,9 @@ void do_fcmpd_fcc2(void);
65 65 void do_fcmps_fcc3(void);
66 66 void do_fcmpd_fcc3(void);
67 67 void do_popc();
  68 +void do_wrpstate();
  69 +void do_done();
  70 +void do_retry();
68 71 #endif
69 72 void do_ldd_kernel(target_ulong addr);
70 73 void do_ldd_user(target_ulong addr);
... ...
target-sparc/helper.c
1 1 /*
2 2 * sparc helpers
3 3 *
4   - * Copyright (c) 2003 Fabrice Bellard
  4 + * Copyright (c) 2003-2005 Fabrice Bellard
5 5 *
6 6 * This library is free software; you can redistribute it and/or
7 7 * modify it under the terms of the GNU Lesser General Public
... ... @@ -28,7 +28,6 @@
28 28 #include "cpu.h"
29 29 #include "exec-all.h"
30 30  
31   -//#define DEBUG_PCALL
32 31 //#define DEBUG_MMU
33 32  
34 33 /* Sparc MMU emulation */
... ... @@ -62,6 +61,9 @@ int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
62 61 #else
63 62  
64 63 #ifndef TARGET_SPARC64
  64 +/*
  65 + * Sparc V8 Reference MMU (SRMMU)
  66 + */
65 67 static const int access_table[8][8] = {
66 68 { 0, 0, 0, 0, 2, 0, 3, 3 },
67 69 { 0, 0, 0, 0, 2, 0, 0, 0 },
... ... @@ -229,6 +231,9 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
229 231 }
230 232 }
231 233 #else
  234 +/*
  235 + * UltraSparc IIi I/DMMUs
  236 + */
232 237 static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
233 238 int *access_index, target_ulong address, int rw,
234 239 int is_user)
... ... @@ -237,46 +242,55 @@ static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical
237 242 unsigned int i;
238 243  
239 244 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
240   - *physical = address & 0xffffffff;
  245 + *physical = address;
241 246 *prot = PAGE_READ | PAGE_WRITE;
242 247 return 0;
243 248 }
244 249  
245 250 for (i = 0; i < 64; i++) {
246   - if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
247   - switch (env->dtlb_tte[i] >> 60) {
248   - default:
249   - case 0x4: // 8k
250   - mask = 0xffffffffffffe000ULL;
251   - break;
252   - case 0x5: // 64k
253   - mask = 0xffffffffffff0000ULL;
254   - break;
255   - case 0x6: // 512k
256   - mask = 0xfffffffffff80000ULL;
257   - break;
258   - case 0x7: // 4M
259   - mask = 0xffffffffffc00000ULL;
260   - break;
261   - }
262   - // ctx match, vaddr match?
263   - if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
264   - (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
265   - // access ok?
266   - if (((env->dtlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) ||
267   - (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
268   - env->exception_index = TT_DFAULT;
269   - return 1;
270   - }
271   - *physical = env->dtlb_tte[i] & 0xffffe000;
272   - *prot = PAGE_READ;
273   - if (env->dtlb_tte[i] & 0x2)
274   - *prot |= PAGE_WRITE;
275   - return 0;
  251 + switch ((env->dtlb_tte[i] >> 61) & 3) {
  252 + default:
  253 + case 0x0: // 8k
  254 + mask = 0xffffffffffffe000ULL;
  255 + break;
  256 + case 0x1: // 64k
  257 + mask = 0xffffffffffff0000ULL;
  258 + break;
  259 + case 0x2: // 512k
  260 + mask = 0xfffffffffff80000ULL;
  261 + break;
  262 + case 0x3: // 4M
  263 + mask = 0xffffffffffc00000ULL;
  264 + break;
  265 + }
  266 + // ctx match, vaddr match?
  267 + if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
  268 + (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
  269 + // valid, access ok?
  270 + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
  271 + ((env->dtlb_tte[i] & 0x4) && is_user) ||
  272 + (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
  273 + if (env->dmmuregs[3]) /* Fault status register */
  274 + env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
  275 + env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
  276 + env->dmmuregs[4] = address; /* Fault address register */
  277 + env->exception_index = TT_DFAULT;
  278 +#ifdef DEBUG_MMU
  279 + printf("DFAULT at 0x%llx\n", address);
  280 +#endif
  281 + return 1;
276 282 }
  283 + *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
  284 + *prot = PAGE_READ;
  285 + if (env->dtlb_tte[i] & 0x2)
  286 + *prot |= PAGE_WRITE;
  287 + return 0;
277 288 }
278 289 }
279   - env->exception_index = TT_DFAULT;
  290 +#ifdef DEBUG_MMU
  291 + printf("DMISS at 0x%llx\n", address);
  292 +#endif
  293 + env->exception_index = TT_DMISS;
280 294 return 1;
281 295 }
282 296  
... ... @@ -288,42 +302,51 @@ static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical
288 302 unsigned int i;
289 303  
290 304 if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
291   - *physical = address & 0xffffffff;
  305 + *physical = address;
292 306 *prot = PAGE_READ;
293 307 return 0;
294 308 }
  309 +
295 310 for (i = 0; i < 64; i++) {
296   - if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
297   - switch (env->itlb_tte[i] >> 60) {
298   - default:
299   - case 0x4: // 8k
300   - mask = 0xffffffffffffe000ULL;
301   - break;
302   - case 0x5: // 64k
303   - mask = 0xffffffffffff0000ULL;
304   - break;
305   - case 0x6: // 512k
306   - mask = 0xfffffffffff80000ULL;
307   - break;
308   - case 0x7: // 4M
309   - mask = 0xffffffffffc00000ULL;
  311 + switch ((env->itlb_tte[i] >> 61) & 3) {
  312 + default:
  313 + case 0x0: // 8k
  314 + mask = 0xffffffffffffe000ULL;
  315 + break;
  316 + case 0x1: // 64k
  317 + mask = 0xffffffffffff0000ULL;
  318 + break;
  319 + case 0x2: // 512k
  320 + mask = 0xfffffffffff80000ULL;
  321 + break;
  322 + case 0x3: // 4M
  323 + mask = 0xffffffffffc00000ULL;
310 324 break;
  325 + }
  326 + // ctx match, vaddr match?
  327 + if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
  328 + (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
  329 + // valid, access ok?
  330 + if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
  331 + ((env->itlb_tte[i] & 0x4) && is_user)) {
  332 + if (env->immuregs[3]) /* Fault status register */
  333 + env->immuregs[3] = 2; /* overflow (not read before another fault) */
  334 + env->immuregs[3] |= (is_user << 3) | 1;
  335 + env->exception_index = TT_TFAULT;
  336 +#ifdef DEBUG_MMU
  337 + printf("TFAULT at 0x%llx\n", address);
  338 +#endif
  339 + return 1;
311 340 }
312   - // ctx match, vaddr match?
313   - if (env->immuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
314   - (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
315   - // access ok?
316   - if ((env->itlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) {
317   - env->exception_index = TT_TFAULT;
318   - return 1;
319   - }
320   - *physical = env->itlb_tte[i] & 0xffffe000;
321   - *prot = PAGE_READ;
322   - return 0;
323   - }
  341 + *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
  342 + *prot = PAGE_READ;
  343 + return 0;
324 344 }
325 345 }
326   - env->exception_index = TT_TFAULT;
  346 +#ifdef DEBUG_MMU
  347 + printf("TMISS at 0x%llx\n", address);
  348 +#endif
  349 + env->exception_index = TT_TMISS;
327 350 return 1;
328 351 }
329 352  
... ... @@ -341,15 +364,17 @@ int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
341 364 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
342 365 int is_user, int is_softmmu)
343 366 {
344   - target_ulong virt_addr;
  367 + target_ulong virt_addr, vaddr;
345 368 target_phys_addr_t paddr;
346   - unsigned long vaddr;
347 369 int error_code = 0, prot, ret = 0, access_index;
348 370  
349 371 error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
350 372 if (error_code == 0) {
351 373 virt_addr = address & TARGET_PAGE_MASK;
352 374 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
  375 +#ifdef DEBUG_MMU
  376 + printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr);
  377 +#endif
353 378 ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
354 379 return ret;
355 380 }
... ... @@ -471,4 +496,77 @@ void dump_mmu(CPUState *env)
471 496 printf("MMU dump ends\n");
472 497 }
473 498 #endif
  499 +#else
  500 +#ifdef DEBUG_MMU
  501 +void dump_mmu(CPUState *env)
  502 +{
  503 + unsigned int i;
  504 + const char *mask;
  505 +
  506 + printf("MMU contexts: Primary: %lld, Secondary: %lld\n", env->dmmuregs[1], env->dmmuregs[2]);
  507 + if ((env->lsu & DMMU_E) == 0) {
  508 + printf("DMMU disabled\n");
  509 + } else {
  510 + printf("DMMU dump:\n");
  511 + for (i = 0; i < 64; i++) {
  512 + switch ((env->dtlb_tte[i] >> 61) & 3) {
  513 + default:
  514 + case 0x0:
  515 + mask = " 8k";
  516 + break;
  517 + case 0x1:
  518 + mask = " 64k";
  519 + break;
  520 + case 0x2:
  521 + mask = "512k";
  522 + break;
  523 + case 0x3:
  524 + mask = " 4M";
  525 + break;
  526 + }
  527 + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
  528 + printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %lld\n",
  529 + env->dtlb_tag[i] & ~0x1fffULL,
  530 + env->dtlb_tte[i] & 0x1ffffffe000ULL,
  531 + mask,
  532 + env->dtlb_tte[i] & 0x4? "priv": "user",
  533 + env->dtlb_tte[i] & 0x2? "RW": "RO",
  534 + env->dtlb_tte[i] & 0x40? "locked": "unlocked",
  535 + env->dtlb_tag[i] & 0x1fffULL);
  536 + }
  537 + }
  538 + }
  539 + if ((env->lsu & IMMU_E) == 0) {
  540 + printf("IMMU disabled\n");
  541 + } else {
  542 + printf("IMMU dump:\n");
  543 + for (i = 0; i < 64; i++) {
  544 + switch ((env->itlb_tte[i] >> 61) & 3) {
  545 + default:
  546 + case 0x0:
  547 + mask = " 8k";
  548 + break;
  549 + case 0x1:
  550 + mask = " 64k";
  551 + break;
  552 + case 0x2:
  553 + mask = "512k";
  554 + break;
  555 + case 0x3:
  556 + mask = " 4M";
  557 + break;
  558 + }
  559 + if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
  560 + printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %lld\n",
  561 + env->itlb_tag[i] & ~0x1fffULL,
  562 + env->itlb_tte[i] & 0x1ffffffe000ULL,
  563 + mask,
  564 + env->itlb_tte[i] & 0x4? "priv": "user",
  565 + env->itlb_tte[i] & 0x40? "locked": "unlocked",
  566 + env->itlb_tag[i] & 0x1fffULL);
  567 + }
  568 + }
  569 + }
  570 +}
  571 +#endif
474 572 #endif
... ...
target-sparc/op.c
... ... @@ -267,15 +267,6 @@
267 267 #endif
268 268  
269 269 #ifdef TARGET_SPARC64
270   -#undef JUMP_TB
271   -#define JUMP_TB(opname, tbparam, n, eip) \
272   - do { \
273   - GOTO_TB(opname, tbparam, n); \
274   - T0 = (long)(tbparam) + (n); \
275   - env->pc = (eip) & 0xffffffff; \
276   - EXIT_TB(); \
277   - } while (0)
278   -
279 270 #ifdef WORDS_BIGENDIAN
280 271 typedef union UREG64 {
281 272 struct { uint16_t v3, v2, v1, v0; } w;
... ... @@ -388,7 +379,7 @@ void OPPROTO op_add_T1_T0_cc(void)
388 379 env->psr |= PSR_ZERO;
389 380 if ((int32_t) T0 < 0)
390 381 env->psr |= PSR_NEG;
391   - if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  382 + if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
392 383 env->psr |= PSR_CARRY;
393 384 if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
394 385 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
... ... @@ -433,7 +424,7 @@ void OPPROTO op_addx_T1_T0_cc(void)
433 424 env->psr |= PSR_ZERO;
434 425 if ((int32_t) T0 < 0)
435 426 env->psr |= PSR_NEG;
436   - if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  427 + if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
437 428 env->psr |= PSR_CARRY;
438 429 if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
439 430 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
... ... @@ -478,7 +469,7 @@ void OPPROTO op_sub_T1_T0_cc(void)
478 469 env->psr |= PSR_ZERO;
479 470 if ((int32_t) T0 < 0)
480 471 env->psr |= PSR_NEG;
481   - if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  472 + if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
482 473 env->psr |= PSR_CARRY;
483 474 if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
484 475 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
... ... @@ -523,7 +514,7 @@ void OPPROTO op_subx_T1_T0_cc(void)
523 514 env->psr |= PSR_ZERO;
524 515 if ((int32_t) T0 < 0)
525 516 env->psr |= PSR_NEG;
526   - if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  517 + if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
527 518 env->psr |= PSR_CARRY;
528 519 if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
529 520 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
... ... @@ -585,7 +576,11 @@ void OPPROTO op_umul_T1_T0(void)
585 576 {
586 577 uint64_t res;
587 578 res = (uint64_t) T0 * (uint64_t) T1;
  579 +#ifdef TARGET_SPARC64
  580 + T0 = res;
  581 +#else
588 582 T0 = res & 0xffffffff;
  583 +#endif
589 584 env->y = res >> 32;
590 585 }
591 586  
... ... @@ -593,7 +588,11 @@ void OPPROTO op_smul_T1_T0(void)
593 588 {
594 589 uint64_t res;
595 590 res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1);
  591 +#ifdef TARGET_SPARC64
  592 + T0 = res;
  593 +#else
596 594 T0 = res & 0xffffffff;
  595 +#endif
597 596 env->y = res >> 32;
598 597 }
599 598  
... ... @@ -902,7 +901,7 @@ void OPPROTO op_rdpstate(void)
902 901  
903 902 void OPPROTO op_wrpstate(void)
904 903 {
905   - env->pstate = T0 & 0x1f;
  904 + do_wrpstate();
906 905 }
907 906  
908 907 // CWP handling is reversed in V9, but we still use the V8 register
... ... @@ -1201,12 +1200,12 @@ void OPPROTO op_eval_xbvc(void)
1201 1200 #ifdef TARGET_SPARC64
1202 1201 void OPPROTO op_eval_brz(void)
1203 1202 {
1204   - T2 = T0;
  1203 + T2 = (T0 == 0);
1205 1204 }
1206 1205  
1207 1206 void OPPROTO op_eval_brnz(void)
1208 1207 {
1209   - T2 = !T0;
  1208 + T2 = (T0 != 0);
1210 1209 }
1211 1210  
1212 1211 void OPPROTO op_eval_brlz(void)
... ... @@ -1266,43 +1265,32 @@ void OPPROTO op_next_insn(void)
1266 1265 env->npc = env->npc + 4;
1267 1266 }
1268 1267  
1269   -void OPPROTO op_branch(void)
  1268 +void OPPROTO op_goto_tb0(void)
1270 1269 {
1271   - env->npc = (uint32_t)PARAM3; /* XXX: optimize */
1272   - JUMP_TB(op_branch, PARAM1, 0, PARAM2);
  1270 + GOTO_TB(op_goto_tb0, PARAM1, 0);
1273 1271 }
1274 1272  
1275   -void OPPROTO op_branch2(void)
  1273 +void OPPROTO op_goto_tb1(void)
1276 1274 {
1277   - if (T2) {
1278   - env->npc = (uint32_t)PARAM2 + 4;
1279   - JUMP_TB(op_branch2, PARAM1, 0, PARAM2);
1280   - } else {
1281   - env->npc = (uint32_t)PARAM3 + 4;
1282   - JUMP_TB(op_branch2, PARAM1, 1, PARAM3);
1283   - }
1284   - FORCE_RET();
  1275 + GOTO_TB(op_goto_tb1, PARAM1, 1);
1285 1276 }
1286 1277  
1287   -void OPPROTO op_branch_a(void)
  1278 +void OPPROTO op_jmp_label(void)
1288 1279 {
1289   - if (T2) {
1290   - env->npc = (uint32_t)PARAM2; /* XXX: optimize */
1291   - JUMP_TB(op_branch_a, PARAM1, 0, PARAM3);
1292   - } else {
1293   - env->npc = (uint32_t)PARAM3 + 8; /* XXX: optimize */
1294   - JUMP_TB(op_branch_a, PARAM1, 1, PARAM3 + 4);
1295   - }
  1280 + GOTO_LABEL_PARAM(1);
  1281 +}
  1282 +
  1283 +void OPPROTO op_jnz_T2_label(void)
  1284 +{
  1285 + if (T2)
  1286 + GOTO_LABEL_PARAM(1);
1296 1287 FORCE_RET();
1297 1288 }
1298 1289  
1299   -void OPPROTO op_generic_branch(void)
  1290 +void OPPROTO op_jz_T2_label(void)
1300 1291 {
1301   - if (T2) {
1302   - env->npc = (uint32_t)PARAM1;
1303   - } else {
1304   - env->npc = (uint32_t)PARAM2;
1305   - }
  1292 + if (!T2)
  1293 + GOTO_LABEL_PARAM(1);
1306 1294 FORCE_RET();
1307 1295 }
1308 1296  
... ... @@ -1547,18 +1535,12 @@ void OPPROTO op_popc(void)
1547 1535  
1548 1536 void OPPROTO op_done(void)
1549 1537 {
1550   - env->pc = env->tnpc[env->tl];
1551   - env->npc = env->tnpc[env->tl] + 4;
1552   - env->pstate = env->tstate[env->tl];
1553   - env->tl--;
  1538 + do_done();
1554 1539 }
1555 1540  
1556 1541 void OPPROTO op_retry(void)
1557 1542 {
1558   - env->pc = env->tpc[env->tl];
1559   - env->npc = env->tnpc[env->tl];
1560   - env->pstate = env->tstate[env->tl];
1561   - env->tl--;
  1543 + do_retry();
1562 1544 }
1563 1545  
1564 1546 void OPPROTO op_sir(void)
... ...
target-sparc/op_helper.c
1 1 #include "exec.h"
2 2  
  3 +//#define DEBUG_PCALL
3 4 //#define DEBUG_MMU
4 5  
5 6 void raise_exception(int tt)
... ... @@ -223,7 +224,7 @@ void do_fcmpd_fcc3 (void)
223 224 #ifndef TARGET_SPARC64
224 225 void helper_ld_asi(int asi, int size, int sign)
225 226 {
226   - uint32_t ret;
  227 + uint32_t ret = 0;
227 228  
228 229 switch (asi) {
229 230 case 3: /* MMU probe */
... ... @@ -299,7 +300,8 @@ void helper_st_asi(int asi, int size, int sign)
299 300 }
300 301 case 4: /* write MMU regs */
301 302 {
302   - int reg = (T0 >> 8) & 0xf, oldreg;
  303 + int reg = (T0 >> 8) & 0xf;
  304 + uint32_t oldreg;
303 305  
304 306 oldreg = env->mmuregs[reg];
305 307 switch(reg) {
... ... @@ -339,7 +341,7 @@ void helper_st_asi(int asi, int size, int sign)
339 341 // value (T1) = src
340 342 // address (T0) = dst
341 343 // copy 32 bytes
342   - int src = T1, dst = T0;
  344 + uint32_t src = T1, dst = T0;
343 345 uint8_t temp[32];
344 346  
345 347 tswap32s(&src);
... ... @@ -353,7 +355,8 @@ void helper_st_asi(int asi, int size, int sign)
353 355 // value (T1, T2)
354 356 // address (T0) = dst
355 357 // fill 32 bytes
356   - int i, dst = T0;
  358 + int i;
  359 + uint32_t dst = T0;
357 360 uint64_t val;
358 361  
359 362 val = (((uint64_t)T1) << 32) | T2;
... ... @@ -366,7 +369,7 @@ void helper_st_asi(int asi, int size, int sign)
366 369 return;
367 370 case 0x20 ... 0x2f: /* MMU passthrough */
368 371 {
369   - int temp = T1;
  372 + uint32_t temp = T1;
370 373 if (size == 4)
371 374 tswap32s(&temp);
372 375 else if (size == 2)
... ... @@ -383,10 +386,10 @@ void helper_st_asi(int asi, int size, int sign)
383 386  
384 387 void helper_ld_asi(int asi, int size, int sign)
385 388 {
386   - uint64_t ret;
  389 + uint64_t ret = 0;
387 390  
388 391 if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
389   - raise_exception(TT_PRIV_INSN);
  392 + raise_exception(TT_PRIV_ACT);
390 393  
391 394 switch (asi) {
392 395 case 0x14: // Bypass
... ... @@ -401,8 +404,23 @@ void helper_ld_asi(int asi, int size, int sign)
401 404 tswap16s((uint16_t *)&ret);
402 405 break;
403 406 }
  407 + case 0x04: // Nucleus
  408 + case 0x0c: // Nucleus Little Endian (LE)
  409 + case 0x10: // As if user primary
  410 + case 0x11: // As if user secondary
  411 + case 0x18: // As if user primary LE
  412 + case 0x19: // As if user secondary LE
404 413 case 0x1c: // Bypass LE
405 414 case 0x1d: // Bypass, non-cacheable LE
  415 + case 0x24: // Nucleus quad LDD 128 bit atomic
  416 + case 0x2c: // Nucleus quad LDD 128 bit atomic
  417 + case 0x4a: // UPA config
  418 + case 0x82: // Primary no-fault
  419 + case 0x83: // Secondary no-fault
  420 + case 0x88: // Primary LE
  421 + case 0x89: // Secondary LE
  422 + case 0x8a: // Primary no-fault LE
  423 + case 0x8b: // Secondary no-fault LE
406 424 // XXX
407 425 break;
408 426 case 0x45: // LSU
... ... @@ -418,8 +436,22 @@ void helper_ld_asi(int asi, int size, int sign)
418 436 case 0x51: // I-MMU 8k TSB pointer
419 437 case 0x52: // I-MMU 64k TSB pointer
420 438 case 0x55: // I-MMU data access
421   - case 0x56: // I-MMU tag read
  439 + // XXX
422 440 break;
  441 + case 0x56: // I-MMU tag read
  442 + {
  443 + unsigned int i;
  444 +
  445 + for (i = 0; i < 64; i++) {
  446 + // Valid, ctx match, vaddr match
  447 + if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
  448 + env->itlb_tag[i] == T0) {
  449 + ret = env->itlb_tag[i];
  450 + break;
  451 + }
  452 + }
  453 + break;
  454 + }
423 455 case 0x58: // D-MMU regs
424 456 {
425 457 int reg = (T0 >> 3) & 0xf;
... ... @@ -427,16 +459,34 @@ void helper_ld_asi(int asi, int size, int sign)
427 459 ret = env->dmmuregs[reg];
428 460 break;
429 461 }
  462 + case 0x5e: // D-MMU tag read
  463 + {
  464 + unsigned int i;
  465 +
  466 + for (i = 0; i < 64; i++) {
  467 + // Valid, ctx match, vaddr match
  468 + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
  469 + env->dtlb_tag[i] == T0) {
  470 + ret = env->dtlb_tag[i];
  471 + break;
  472 + }
  473 + }
  474 + break;
  475 + }
430 476 case 0x59: // D-MMU 8k TSB pointer
431 477 case 0x5a: // D-MMU 64k TSB pointer
432 478 case 0x5b: // D-MMU data pointer
433 479 case 0x5d: // D-MMU data access
434   - case 0x5e: // D-MMU tag read
  480 + case 0x48: // Interrupt dispatch, RO
  481 + case 0x49: // Interrupt data receive
  482 + case 0x7f: // Incoming interrupt vector, RO
  483 + // XXX
435 484 break;
436 485 case 0x54: // I-MMU data in, WO
437 486 case 0x57: // I-MMU demap, WO
438 487 case 0x5c: // D-MMU data in, WO
439 488 case 0x5f: // D-MMU demap, WO
  489 + case 0x77: // Interrupt vector, WO
440 490 default:
441 491 ret = 0;
442 492 break;
... ... @@ -447,7 +497,7 @@ void helper_ld_asi(int asi, int size, int sign)
447 497 void helper_st_asi(int asi, int size, int sign)
448 498 {
449 499 if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
450   - raise_exception(TT_PRIV_INSN);
  500 + raise_exception(TT_PRIV_ACT);
451 501  
452 502 switch(asi) {
453 503 case 0x14: // Bypass
... ... @@ -463,8 +513,19 @@ void helper_st_asi(int asi, int size, int sign)
463 513 cpu_physical_memory_write(T0, (void *) &temp, size);
464 514 }
465 515 return;
  516 + case 0x04: // Nucleus
  517 + case 0x0c: // Nucleus Little Endian (LE)
  518 + case 0x10: // As if user primary
  519 + case 0x11: // As if user secondary
  520 + case 0x18: // As if user primary LE
  521 + case 0x19: // As if user secondary LE
466 522 case 0x1c: // Bypass LE
467 523 case 0x1d: // Bypass, non-cacheable LE
  524 + case 0x24: // Nucleus quad LDD 128 bit atomic
  525 + case 0x2c: // Nucleus quad LDD 128 bit atomic
  526 + case 0x4a: // UPA config
  527 + case 0x88: // Primary LE
  528 + case 0x89: // Secondary LE
468 529 // XXX
469 530 return;
470 531 case 0x45: // LSU
... ... @@ -475,8 +536,13 @@ void helper_st_asi(int asi, int size, int sign)
475 536 env->lsu = T1 & (DMMU_E | IMMU_E);
476 537 // Mappings generated during D/I MMU disabled mode are
477 538 // invalid in normal mode
478   - if (oldreg != env->lsu)
  539 + if (oldreg != env->lsu) {
  540 +#ifdef DEBUG_MMU
  541 + printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
  542 + dump_mmu(env);
  543 +#endif
479 544 tlb_flush(env, 1);
  545 + }
480 546 return;
481 547 }
482 548 case 0x50: // I-MMU regs
... ... @@ -506,7 +572,7 @@ void helper_st_asi(int asi, int size, int sign)
506 572 env->immuregs[reg] = T1;
507 573 #ifdef DEBUG_MMU
508 574 if (oldreg != env->immuregs[reg]) {
509   - printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]);
  575 + printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
510 576 }
511 577 dump_mmu(env);
512 578 #endif
... ... @@ -544,6 +610,7 @@ void helper_st_asi(int asi, int size, int sign)
544 610 return;
545 611 }
546 612 case 0x57: // I-MMU demap
  613 + // XXX
547 614 return;
548 615 case 0x58: // D-MMU regs
549 616 {
... ... @@ -574,7 +641,7 @@ void helper_st_asi(int asi, int size, int sign)
574 641 env->dmmuregs[reg] = T1;
575 642 #ifdef DEBUG_MMU
576 643 if (oldreg != env->dmmuregs[reg]) {
577   - printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]);
  644 + printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
578 645 }
579 646 dump_mmu(env);
580 647 #endif
... ... @@ -612,6 +679,8 @@ void helper_st_asi(int asi, int size, int sign)
612 679 return;
613 680 }
614 681 case 0x5f: // D-MMU demap
  682 + case 0x49: // Interrupt data receive
  683 + // XXX
615 684 return;
616 685 case 0x51: // I-MMU 8k TSB pointer, RO
617 686 case 0x52: // I-MMU 64k TSB pointer, RO
... ... @@ -620,6 +689,12 @@ void helper_st_asi(int asi, int size, int sign)
620 689 case 0x5a: // D-MMU 64k TSB pointer, RO
621 690 case 0x5b: // D-MMU data pointer, RO
622 691 case 0x5e: // D-MMU tag read, RO
  692 + case 0x48: // Interrupt dispatch, RO
  693 + case 0x7f: // Incoming interrupt vector, RO
  694 + case 0x82: // Primary no-fault, RO
  695 + case 0x83: // Secondary no-fault, RO
  696 + case 0x8a: // Primary no-fault LE, RO
  697 + case 0x8b: // Secondary no-fault LE, RO
623 698 default:
624 699 return;
625 700 }
... ... @@ -704,6 +779,61 @@ void do_popc()
704 779 T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
705 780 T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
706 781 }
  782 +
  783 +static inline uint64_t *get_gregset(uint64_t pstate)
  784 +{
  785 + switch (pstate) {
  786 + default:
  787 + case 0:
  788 + return env->bgregs;
  789 + case PS_AG:
  790 + return env->agregs;
  791 + case PS_MG:
  792 + return env->mgregs;
  793 + case PS_IG:
  794 + return env->igregs;
  795 + }
  796 +}
  797 +
  798 +void do_wrpstate()
  799 +{
  800 + uint64_t new_pstate, pstate_regs, new_pstate_regs;
  801 + uint64_t *src, *dst;
  802 +
  803 + new_pstate = T0 & 0xf3f;
  804 + pstate_regs = env->pstate & 0xc01;
  805 + new_pstate_regs = new_pstate & 0xc01;
  806 + if (new_pstate_regs != pstate_regs) {
  807 + // Switch global register bank
  808 + src = get_gregset(new_pstate_regs);
  809 + dst = get_gregset(pstate_regs);
  810 + memcpy32(dst, env->gregs);
  811 + memcpy32(env->gregs, src);
  812 + }
  813 + env->pstate = new_pstate;
  814 +}
  815 +
  816 +void do_done(void)
  817 +{
  818 + env->tl--;
  819 + env->pc = env->tnpc[env->tl];
  820 + env->npc = env->tnpc[env->tl] + 4;
  821 + PUT_CCR(env, env->tstate[env->tl] >> 32);
  822 + env->asi = (env->tstate[env->tl] >> 24) & 0xff;
  823 + env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
  824 + set_cwp(env->tstate[env->tl] & 0xff);
  825 +}
  826 +
  827 +void do_retry(void)
  828 +{
  829 + env->tl--;
  830 + env->pc = env->tpc[env->tl];
  831 + env->npc = env->tnpc[env->tl];
  832 + PUT_CCR(env, env->tstate[env->tl] >> 32);
  833 + env->asi = (env->tstate[env->tl] >> 24) & 0xff;
  834 + env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
  835 + set_cwp(env->tstate[env->tl] & 0xff);
  836 +}
707 837 #endif
708 838  
709 839 void set_cwp(int new_cwp)
... ... @@ -744,7 +874,7 @@ void do_interrupt(int intno)
744 874 #ifdef DEBUG_PCALL
745 875 if (loglevel & CPU_LOG_INT) {
746 876 static int count;
747   - fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
  877 + fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
748 878 count, intno,
749 879 env->pc,
750 880 env->npc, env->regwptr[6]);
... ... @@ -766,8 +896,8 @@ void do_interrupt(int intno)
766 896 }
767 897 #endif
768 898 #if !defined(CONFIG_USER_ONLY)
769   - if (env->pstate & PS_IE) {
770   - cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
  899 + if (env->tl == MAXTL) {
  900 + cpu_abort(cpu_single_env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
771 901 return;
772 902 }
773 903 #endif
... ... @@ -776,8 +906,16 @@ void do_interrupt(int intno)
776 906 env->tpc[env->tl] = env->pc;
777 907 env->tnpc[env->tl] = env->npc;
778 908 env->tt[env->tl] = intno;
779   - env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4);
780   - env->tl++;
  909 + env->pstate = PS_PEF | PS_PRIV | PS_AG;
  910 + env->tbr &= ~0x7fffULL;
  911 + env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
  912 + if (env->tl < MAXTL - 1) {
  913 + env->tl++;
  914 + } else {
  915 + env->pstate |= PS_RED;
  916 + if (env->tl != MAXTL)
  917 + env->tl++;
  918 + }
781 919 env->pc = env->tbr;
782 920 env->npc = env->pc + 4;
783 921 env->exception_index = 0;
... ...
target-sparc/op_mem.h
... ... @@ -105,20 +105,10 @@ void OPPROTO glue(op_casx, MEMSUFFIX)(void)
105 105  
106 106 void OPPROTO glue(op_ldsw, MEMSUFFIX)(void)
107 107 {
108   - T1 = (int64_t)glue(ldl, MEMSUFFIX)(T0);
  108 + T1 = (int64_t)(glue(ldl, MEMSUFFIX)(T0) & 0xffffffff);
109 109 }
110 110  
111   -void OPPROTO glue(op_ldx, MEMSUFFIX)(void)
112   -{
113   - // XXX
114   - T1 = (uint64_t)glue(ldl, MEMSUFFIX)(T0) << 32;
115   - T1 |= glue(ldl, MEMSUFFIX)(T0);
116   -}
117   -
118   -void OPPROTO glue(op_stx, MEMSUFFIX)(void)
119   -{
120   - glue(stl, MEMSUFFIX)(T0, T1 >> 32);
121   - glue(stl, MEMSUFFIX)(T0, T1 & 0xffffffff);
122   -}
  111 +SPARC_LD_OP(ldx, ldq);
  112 +SPARC_ST_OP(stx, stq);
123 113 #endif
124 114 #undef MEMSUFFIX
... ...
target-sparc/translate.c
... ... @@ -86,6 +86,12 @@ enum {
86 86 #define DFPREG(r) (r)
87 87 #endif
88 88  
  89 +#ifdef USE_DIRECT_JUMP
  90 +#define TBPARAM(x)
  91 +#else
  92 +#define TBPARAM(x) (long)(x)
  93 +#endif
  94 +
89 95 static int sign_extend(int x, int len)
90 96 {
91 97 len = 32 - len;
... ... @@ -462,7 +468,7 @@ OP_LD_TABLE(casx);
462 468  
463 469 static inline void gen_movl_imm_TN(int reg, uint32_t imm)
464 470 {
465   - gen_op_movl_TN_im[reg] (imm);
  471 + gen_op_movl_TN_im[reg](imm);
466 472 }
467 473  
468 474 static inline void gen_movl_imm_T1(uint32_t val)
... ... @@ -529,15 +535,6 @@ static inline void gen_movl_T1_reg(int reg)
529 535 gen_movl_TN_reg(reg, 1);
530 536 }
531 537  
532   -/* call this function before using T2 as it may have been set for a jump */
533   -static inline void flush_T2(DisasContext * dc)
534   -{
535   - if (dc->npc == JUMP_PC) {
536   - gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
537   - dc->npc = DYNAMIC_PC;
538   - }
539   -}
540   -
541 538 static inline void gen_jmp_im(target_ulong pc)
542 539 {
543 540 #ifdef TARGET_SPARC64
... ... @@ -564,10 +561,88 @@ static inline void gen_movl_npc_im(target_ulong npc)
564 561 #endif
565 562 }
566 563  
  564 +static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
  565 +{
  566 + int l1;
  567 +
  568 + l1 = gen_new_label();
  569 +
  570 + gen_op_jz_T2_label(l1);
  571 +
  572 + gen_op_goto_tb0(TBPARAM(tb));
  573 + gen_jmp_im(pc1);
  574 + gen_movl_npc_im(pc1 + 4);
  575 + gen_op_movl_T0_im((long)tb + 0);
  576 + gen_op_exit_tb();
  577 +
  578 + gen_set_label(l1);
  579 + gen_op_goto_tb1(TBPARAM(tb));
  580 + gen_jmp_im(pc2);
  581 + gen_movl_npc_im(pc2 + 4);
  582 + gen_op_movl_T0_im((long)tb + 1);
  583 + gen_op_exit_tb();
  584 +}
  585 +
  586 +static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
  587 +{
  588 + int l1;
  589 +
  590 + l1 = gen_new_label();
  591 +
  592 + gen_op_jz_T2_label(l1);
  593 +
  594 + gen_op_goto_tb0(TBPARAM(tb));
  595 + gen_jmp_im(pc2);
  596 + gen_movl_npc_im(pc1);
  597 + gen_op_movl_T0_im((long)tb + 0);
  598 + gen_op_exit_tb();
  599 +
  600 + gen_set_label(l1);
  601 + gen_op_goto_tb1(TBPARAM(tb));
  602 + gen_jmp_im(pc2 + 4);
  603 + gen_movl_npc_im(pc2 + 8);
  604 + gen_op_movl_T0_im((long)tb + 1);
  605 + gen_op_exit_tb();
  606 +}
  607 +
  608 +static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
  609 +{
  610 + gen_op_goto_tb0(TBPARAM(tb));
  611 + gen_jmp_im(pc);
  612 + gen_movl_npc_im(npc);
  613 + gen_op_movl_T0_im((long)tb + 0);
  614 + gen_op_exit_tb();
  615 +}
  616 +
  617 +static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2)
  618 +{
  619 + int l1, l2;
  620 +
  621 + l1 = gen_new_label();
  622 + l2 = gen_new_label();
  623 + gen_op_jz_T2_label(l1);
  624 +
  625 + gen_movl_npc_im(npc1);
  626 + gen_op_jmp_label(l2);
  627 +
  628 + gen_set_label(l1);
  629 + gen_movl_npc_im(npc2);
  630 + gen_set_label(l2);
  631 +}
  632 +
  633 +/* call this function before using T2 as it may have been set for a jump */
  634 +static inline void flush_T2(DisasContext * dc)
  635 +{
  636 + if (dc->npc == JUMP_PC) {
  637 + gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
  638 + dc->npc = DYNAMIC_PC;
  639 + }
  640 +}
  641 +
567 642 static inline void save_npc(DisasContext * dc)
568 643 {
569 644 if (dc->npc == JUMP_PC) {
570   - gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
  645 + gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
571 646 dc->npc = DYNAMIC_PC;
572 647 } else if (dc->npc != DYNAMIC_PC) {
573 648 gen_movl_npc_im(dc->npc);
... ... @@ -583,7 +658,7 @@ static inline void save_state(DisasContext * dc)
583 658 static inline void gen_mov_pc_npc(DisasContext * dc)
584 659 {
585 660 if (dc->npc == JUMP_PC) {
586   - gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
  661 + gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
587 662 gen_op_mov_pc_npc();
588 663 dc->pc = DYNAMIC_PC;
589 664 } else if (dc->npc == DYNAMIC_PC) {
... ... @@ -769,7 +844,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
769 844 flush_T2(dc);
770 845 gen_cond[cc][cond]();
771 846 if (a) {
772   - gen_op_branch_a((long)dc->tb, target, dc->npc);
  847 + gen_branch_a(dc, (long)dc->tb, target, dc->npc);
773 848 dc->is_br = 1;
774 849 } else {
775 850 dc->pc = dc->npc;
... ... @@ -808,7 +883,7 @@ static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
808 883 flush_T2(dc);
809 884 gen_fcond[cc][cond]();
810 885 if (a) {
811   - gen_op_branch_a((long)dc->tb, target, dc->npc);
  886 + gen_branch_a(dc, (long)dc->tb, target, dc->npc);
812 887 dc->is_br = 1;
813 888 } else {
814 889 dc->pc = dc->npc;
... ... @@ -829,7 +904,7 @@ static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
829 904 flush_T2(dc);
830 905 gen_cond_reg(cond);
831 906 if (a) {
832   - gen_op_branch_a((long)dc->tb, target, dc->npc);
  907 + gen_branch_a(dc, (long)dc->tb, target, dc->npc);
833 908 dc->is_br = 1;
834 909 } else {
835 910 dc->pc = dc->npc;
... ... @@ -893,7 +968,7 @@ static void disas_sparc_insn(DisasContext * dc)
893 968 target <<= 2;
894 969 target = sign_extend(target, 16);
895 970 rs1 = GET_FIELD(insn, 13, 17);
896   - gen_movl_T0_reg(rs1);
  971 + gen_movl_reg_T0(rs1);
897 972 do_branch_reg(dc, target, insn);
898 973 goto jmp_insn;
899 974 }
... ... @@ -952,7 +1027,15 @@ static void disas_sparc_insn(DisasContext * dc)
952 1027 /*CALL*/ {
953 1028 target_long target = GET_FIELDs(insn, 2, 31) << 2;
954 1029  
  1030 +#ifdef TARGET_SPARC64
  1031 + if (dc->pc == (uint32_t)dc->pc) {
  1032 + gen_op_movl_T0_im(dc->pc);
  1033 + } else {
  1034 + gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
  1035 + }
  1036 +#else
955 1037 gen_op_movl_T0_im(dc->pc);
  1038 +#endif
956 1039 gen_movl_T0_reg(15);
957 1040 target += dc->pc;
958 1041 gen_mov_pc_npc(dc);
... ... @@ -1039,6 +1122,25 @@ static void disas_sparc_insn(DisasContext * dc)
1039 1122 gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
1040 1123 gen_movl_T0_reg(rd);
1041 1124 break;
  1125 + case 0x17: /* Tick compare */
  1126 + gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
  1127 + gen_movl_T0_reg(rd);
  1128 + break;
  1129 + case 0x18: /* System tick */
  1130 + gen_op_rdtick(); // XXX
  1131 + gen_movl_T0_reg(rd);
  1132 + break;
  1133 + case 0x19: /* System tick compare */
  1134 + gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
  1135 + gen_movl_T0_reg(rd);
  1136 + break;
  1137 + case 0x10: /* Performance Control */
  1138 + case 0x11: /* Performance Instrumentation Counter */
  1139 + case 0x12: /* Dispatch Control */
  1140 + case 0x13: /* Graphics Status */
  1141 + case 0x14: /* Softint set, WO */
  1142 + case 0x15: /* Softint clear, WO */
  1143 + case 0x16: /* Softint write */
1042 1144 #endif
1043 1145 default:
1044 1146 goto illegal_insn;
... ... @@ -1549,6 +1651,50 @@ static void disas_sparc_insn(DisasContext * dc)
1549 1651 gen_movl_T0_reg(rd);
1550 1652 }
1551 1653 #endif
  1654 +#ifdef TARGET_SPARC64
  1655 + } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */
  1656 + rs1 = GET_FIELD(insn, 13, 17);
  1657 + gen_movl_reg_T0(rs1);
  1658 + if (IS_IMM) { /* immediate */
  1659 + rs2 = GET_FIELDs(insn, 20, 31);
  1660 + gen_movl_simm_T1(rs2);
  1661 + } else { /* register */
  1662 + rs2 = GET_FIELD(insn, 27, 31);
  1663 + gen_movl_reg_T1(rs2);
  1664 + }
  1665 + gen_op_sll();
  1666 + gen_movl_T0_reg(rd);
  1667 + } else if (xop == 0x26) { /* srl, V9 srlx */
  1668 + rs1 = GET_FIELD(insn, 13, 17);
  1669 + gen_movl_reg_T0(rs1);
  1670 + if (IS_IMM) { /* immediate */
  1671 + rs2 = GET_FIELDs(insn, 20, 31);
  1672 + gen_movl_simm_T1(rs2);
  1673 + } else { /* register */
  1674 + rs2 = GET_FIELD(insn, 27, 31);
  1675 + gen_movl_reg_T1(rs2);
  1676 + }
  1677 + if (insn & (1 << 12))
  1678 + gen_op_srlx();
  1679 + else
  1680 + gen_op_srl();
  1681 + gen_movl_T0_reg(rd);
  1682 + } else if (xop == 0x27) { /* sra, V9 srax */
  1683 + rs1 = GET_FIELD(insn, 13, 17);
  1684 + gen_movl_reg_T0(rs1);
  1685 + if (IS_IMM) { /* immediate */
  1686 + rs2 = GET_FIELDs(insn, 20, 31);
  1687 + gen_movl_simm_T1(rs2);
  1688 + } else { /* register */
  1689 + rs2 = GET_FIELD(insn, 27, 31);
  1690 + gen_movl_reg_T1(rs2);
  1691 + }
  1692 + if (insn & (1 << 12))
  1693 + gen_op_srax();
  1694 + else
  1695 + gen_op_sra();
  1696 + gen_movl_T0_reg(rd);
  1697 +#endif
1552 1698 } else if (xop < 0x38) {
1553 1699 rs1 = GET_FIELD(insn, 13, 17);
1554 1700 gen_movl_reg_T0(rs1);
... ... @@ -1660,32 +1806,20 @@ static void disas_sparc_insn(DisasContext * dc)
1660 1806 gen_op_mulscc_T1_T0();
1661 1807 gen_movl_T0_reg(rd);
1662 1808 break;
1663   - case 0x25: /* sll, V9 sllx ( == sll) */
  1809 +#ifndef TARGET_SPARC64
  1810 + case 0x25: /* sll */
1664 1811 gen_op_sll();
1665 1812 gen_movl_T0_reg(rd);
1666 1813 break;
1667   - case 0x26: /* srl, V9 srlx */
1668   -#ifdef TARGET_SPARC64
1669   - if (insn & (1 << 12))
1670   - gen_op_srlx();
1671   - else
1672   - gen_op_srl();
1673   -#else
  1814 + case 0x26: /* srl */
1674 1815 gen_op_srl();
1675   -#endif
1676 1816 gen_movl_T0_reg(rd);
1677 1817 break;
1678   - case 0x27: /* sra, V9 srax */
1679   -#ifdef TARGET_SPARC64
1680   - if (insn & (1 << 12))
1681   - gen_op_srax();
1682   - else
1683   - gen_op_sra();
1684   -#else
  1818 + case 0x27: /* sra */
1685 1819 gen_op_sra();
1686   -#endif
1687 1820 gen_movl_T0_reg(rd);
1688 1821 break;
  1822 +#endif
1689 1823 case 0x30:
1690 1824 {
1691 1825 switch(rd) {
... ... @@ -1709,7 +1843,28 @@ static void disas_sparc_insn(DisasContext * dc)
1709 1843 gen_op_sir();
1710 1844 #endif
1711 1845 break;
  1846 + case 0x17: /* Tick compare */
  1847 +#if !defined(CONFIG_USER_ONLY)
  1848 + if (!supervisor(dc))
  1849 + goto illegal_insn;
  1850 +#endif
  1851 + gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
  1852 + break;
  1853 + case 0x18: /* System tick */
  1854 +#if !defined(CONFIG_USER_ONLY)
  1855 + if (!supervisor(dc))
  1856 + goto illegal_insn;
  1857 +#endif
  1858 + gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
  1859 + break;
  1860 + case 0x19: /* System tick compare */
  1861 +#if !defined(CONFIG_USER_ONLY)
  1862 + if (!supervisor(dc))
  1863 + goto illegal_insn;
1712 1864 #endif
  1865 + gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
  1866 + break;
  1867 +
1713 1868 case 0x10: /* Performance Control */
1714 1869 case 0x11: /* Performance Instrumentation Counter */
1715 1870 case 0x12: /* Dispatch Control */
... ... @@ -1717,9 +1872,7 @@ static void disas_sparc_insn(DisasContext * dc)
1717 1872 case 0x14: /* Softint set */
1718 1873 case 0x15: /* Softint clear */
1719 1874 case 0x16: /* Softint write */
1720   - case 0x17: /* Tick compare */
1721   - case 0x18: /* System tick */
1722   - case 0x19: /* System tick compare */
  1875 +#endif
1723 1876 default:
1724 1877 goto illegal_insn;
1725 1878 }
... ... @@ -1770,7 +1923,7 @@ static void disas_sparc_insn(DisasContext * dc)
1770 1923 gen_op_wrtick();
1771 1924 break;
1772 1925 case 5: // tba
1773   - gen_op_movl_env_T0(offsetof(CPUSPARCState, tbr));
  1926 + gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
1774 1927 break;
1775 1928 case 6: // pstate
1776 1929 gen_op_wrpstate();
... ... @@ -1896,7 +2049,6 @@ static void disas_sparc_insn(DisasContext * dc)
1896 2049 }
1897 2050 #ifdef TARGET_SPARC64
1898 2051 } else if (xop == 0x39) { /* V9 return */
1899   - gen_op_restore();
1900 2052 rs1 = GET_FIELD(insn, 13, 17);
1901 2053 gen_movl_reg_T0(rs1);
1902 2054 if (IS_IMM) { /* immediate */
... ... @@ -1920,6 +2072,7 @@ static void disas_sparc_insn(DisasContext * dc)
1920 2072 }
1921 2073 #endif
1922 2074 }
  2075 + gen_op_restore();
1923 2076 gen_mov_pc_npc(dc);
1924 2077 gen_op_movl_npc_T0();
1925 2078 dc->npc = DYNAMIC_PC;
... ... @@ -1993,13 +2146,17 @@ static void disas_sparc_insn(DisasContext * dc)
1993 2146 case 0:
1994 2147 if (!supervisor(dc))
1995 2148 goto priv_insn;
  2149 + dc->npc = DYNAMIC_PC;
  2150 + dc->pc = DYNAMIC_PC;
1996 2151 gen_op_done();
1997   - break;
  2152 + goto jmp_insn;
1998 2153 case 1:
1999 2154 if (!supervisor(dc))
2000 2155 goto priv_insn;
  2156 + dc->npc = DYNAMIC_PC;
  2157 + dc->pc = DYNAMIC_PC;
2001 2158 gen_op_retry();
2002   - break;
  2159 + goto jmp_insn;
2003 2160 default:
2004 2161 goto illegal_insn;
2005 2162 }
... ... @@ -2317,7 +2474,7 @@ static void disas_sparc_insn(DisasContext * dc)
2317 2474 gen_op_next_insn();
2318 2475 } else if (dc->npc == JUMP_PC) {
2319 2476 /* we can do a static jump */
2320   - gen_op_branch2((long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
  2477 + gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
2321 2478 dc->is_br = 1;
2322 2479 } else {
2323 2480 dc->pc = dc->npc;
... ... @@ -2365,6 +2522,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2365 2522 gen_opc_ptr = gen_opc_buf;
2366 2523 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2367 2524 gen_opparam_ptr = gen_opparam_buf;
  2525 + nb_gen_labels = 0;
2368 2526  
2369 2527 do {
2370 2528 if (env->nb_breakpoints > 0) {
... ... @@ -2421,7 +2579,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2421 2579 if (dc->pc != DYNAMIC_PC &&
2422 2580 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2423 2581 /* static PC and NPC: we can use direct chaining */
2424   - gen_op_branch((long)tb, dc->pc, dc->npc);
  2582 + gen_branch(dc, (long)tb, dc->pc, dc->npc);
2425 2583 } else {
2426 2584 if (dc->pc != DYNAMIC_PC)
2427 2585 gen_jmp_im(dc->pc);
... ... @@ -2487,15 +2645,16 @@ void cpu_reset(CPUSPARCState *env)
2487 2645 #else
2488 2646 env->psrs = 1;
2489 2647 env->psrps = 1;
2490   - env->pc = 0xffd00000;
2491 2648 env->gregs[1] = ram_size;
2492   - env->npc = env->pc + 4;
2493 2649 #ifdef TARGET_SPARC64
2494   - env->pstate = PS_AM | PS_PRIV; // XXX: Force AM
  2650 + env->pstate = PS_PRIV;
2495 2651 env->version = GET_VER(env);
  2652 + env->pc = 0x1fff0000000ULL;
2496 2653 #else
2497 2654 env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
  2655 + env->pc = 0xffd00000;
2498 2656 #endif
  2657 + env->npc = env->pc + 4;
2499 2658 #endif
2500 2659 }
2501 2660  
... ...
... ... @@ -559,6 +559,7 @@ void pci_set_pic(PCIBus *bus, SetIRQFunc *set_irq, void *irq_opaque);
559 559 PCIBus *pci_prep_init(void);
560 560 PCIBus *pci_grackle_init(uint32_t base);
561 561 PCIBus *pci_pmac_init(void);
  562 +PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base);
562 563  
563 564 /* openpic.c */
564 565 typedef struct openpic_t openpic_t;
... ...