Mercurial > audlegacy-plugins
comparison src/console/Ay_Cpu.cxx @ 341:986f098da058 trunk
[svn] - merge in blargg's changes
author | nenolod |
---|---|
date | Thu, 07 Dec 2006 15:20:41 -0800 |
parents | fb513e10174e |
children |
comparison
equal
deleted
inserted
replaced
340:9e5a7158fa80 | 341:986f098da058 |
---|---|
1 // Game_Music_Emu 0.5.1. http://www.slack.net/~ant/ | 1 // Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ |
2 | 2 |
3 // Last validated with zexall 2006.11.21 5:26 PM | 3 /* |
4 // Doesn't implement interrupts or the R register, though both would be | 4 Last validated with zexall 2006.11.21 5:26 PM |
5 // easy to support. | 5 * Doesn't implement the R register or immediate interrupt after EI. |
6 * Address wrap-around isn't completely correct, but is prevented from crashing emulator. | |
7 */ | |
6 | 8 |
7 #include "Ay_Cpu.h" | 9 #include "Ay_Cpu.h" |
8 | 10 |
9 #include "blargg_endian.h" | 11 #include "blargg_endian.h" |
10 #include <string.h> | 12 #include <string.h> |
25 #define SYNC_TIME() (void) (s.time = s_time) | 27 #define SYNC_TIME() (void) (s.time = s_time) |
26 #define RELOAD_TIME() (void) (s_time = s.time) | 28 #define RELOAD_TIME() (void) (s_time = s.time) |
27 | 29 |
28 // Callbacks to emulator | 30 // Callbacks to emulator |
29 | 31 |
30 #define CPU_OUT( cpu, addr, data, TIME ) \ | 32 #define CPU_OUT( cpu, addr, data, TIME )\ |
31 ay_cpu_out( cpu, TIME, addr, data ) | 33 ay_cpu_out( cpu, TIME, addr, data ) |
32 | 34 |
33 #define CPU_IN( cpu, addr, TIME ) \ | 35 #define CPU_IN( cpu, addr, TIME )\ |
34 ay_cpu_in( cpu, addr ) | 36 ay_cpu_in( cpu, addr ) |
35 | 37 |
36 #include "blargg_source.h" | 38 #include "blargg_source.h" |
37 | 39 |
38 // flags, named with hex value for clarity | 40 // flags, named with hex value for clarity |
103 #endif | 105 #endif |
104 | 106 |
105 //#define R16( n, shift, offset ) (r16_ [((n) >> shift) - (offset >> shift)]) | 107 //#define R16( n, shift, offset ) (r16_ [((n) >> shift) - (offset >> shift)]) |
106 | 108 |
107 // help compiler see that it can just adjust stack offset, saving an extra instruction | 109 // help compiler see that it can just adjust stack offset, saving an extra instruction |
108 #define R16( n, shift, offset ) \ | 110 #define R16( n, shift, offset )\ |
109 (*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1)))) | 111 (*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1)))) |
110 | 112 |
111 #define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e | 113 #define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e |
112 #define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f | 114 #define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f |
113 #define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g | 115 #define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g |
352 sp = uint16_t (sp - 2); | 354 sp = uint16_t (sp - 2); |
353 WRITE_WORD( sp, addr ); | 355 WRITE_WORD( sp, addr ); |
354 goto loop; | 356 goto loop; |
355 } | 357 } |
356 | 358 |
357 CASE8( C7, CF, D7, DF, E7, EF, F7, FF ): // RST | 359 case 0xFF: // RST |
360 if ( (pc - 1) > 0xFFFF ) | |
361 { | |
362 pc = uint16_t (pc - 1); | |
363 s_time -= 11; | |
364 goto loop; | |
365 } | |
366 CASE7( C7, CF, D7, DF, E7, EF, F7 ): | |
358 data = pc; | 367 data = pc; |
359 pc = opcode & 0x38; | 368 pc = opcode & 0x38; |
360 goto push_data; | 369 goto push_data; |
361 | 370 |
362 // PUSH/POP | 371 // PUSH/POP |
1295 pc++; | 1304 pc++; |
1296 unsigned data2 = READ_PROG( pc ); | 1305 unsigned data2 = READ_PROG( pc ); |
1297 s_time += ed_dd_timing [data] & 0x0F; | 1306 s_time += ed_dd_timing [data] & 0x0F; |
1298 switch ( data ) | 1307 switch ( data ) |
1299 { | 1308 { |
1309 // TODO: more efficient way of avoid negative address | |
1310 #define IXY_DISP( ixy, disp ) uint16_t ((ixy) + (disp)) | |
1311 | |
1300 #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in; | 1312 #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in; |
1301 | 1313 |
1302 // ADD/ADC/SUB/SBC | 1314 // ADD/ADC/SUB/SBC |
1303 | 1315 |
1304 case 0x96: // SUB (IXY+disp) | 1316 case 0x96: // SUB (IXY+disp) |
1306 flags &= ~C01; | 1318 flags &= ~C01; |
1307 case 0x9E: // SBC (IXY+disp) | 1319 case 0x9E: // SBC (IXY+disp) |
1308 case 0x8E: // ADC (IXY+disp) | 1320 case 0x8E: // ADC (IXY+disp) |
1309 pc++; | 1321 pc++; |
1310 opcode = data; | 1322 opcode = data; |
1311 data = READ( ixy + (int8_t) data2 ); | 1323 data = READ( IXY_DISP( ixy, (int8_t) data2 ) ); |
1312 goto adc_data; | 1324 goto adc_data; |
1313 | 1325 |
1314 case 0x94: // SUB HXY | 1326 case 0x94: // SUB HXY |
1315 case 0x84: // ADD HXY | 1327 case 0x84: // ADD HXY |
1316 flags &= ~C01; | 1328 flags &= ~C01; |
1328 opcode = data; | 1340 opcode = data; |
1329 data = (uint8_t) ixy; | 1341 data = (uint8_t) ixy; |
1330 goto adc_data; | 1342 goto adc_data; |
1331 | 1343 |
1332 { | 1344 { |
1333 unsigned data2; | 1345 unsigned temp; |
1334 case 0x39: // ADD IXY,SP | 1346 case 0x39: // ADD IXY,SP |
1335 data2 = sp; | 1347 temp = sp; |
1336 goto add_ixy_data; | 1348 goto add_ixy_data; |
1337 | 1349 |
1338 case 0x29: // ADD IXY,HL | 1350 case 0x29: // ADD IXY,HL |
1339 data2 = ixy; | 1351 temp = ixy; |
1340 goto add_ixy_data; | 1352 goto add_ixy_data; |
1341 | 1353 |
1342 case 0x09: // ADD IXY,BC | 1354 case 0x09: // ADD IXY,BC |
1343 case 0x19: // ADD IXY,DE | 1355 case 0x19: // ADD IXY,DE |
1344 data2 = R16( data, 4, 0x09 ); | 1356 temp = R16( data, 4, 0x09 ); |
1345 add_ixy_data: { | 1357 add_ixy_data: { |
1346 blargg_ulong sum = ixy + data2; | 1358 blargg_ulong sum = ixy + temp; |
1347 data2 ^= ixy; | 1359 temp ^= ixy; |
1348 ixy = sum; | 1360 ixy = (uint16_t) sum; |
1349 flags = (flags & (S80 | Z40 | V04)) | | 1361 flags = (flags & (S80 | Z40 | V04)) | |
1350 (sum >> 16) | | 1362 (sum >> 16) | |
1351 (sum >> 8 & (F20 | F08)) | | 1363 (sum >> 8 & (F20 | F08)) | |
1352 ((data2 ^ sum) >> 8 & H10); | 1364 ((temp ^ sum) >> 8 & H10); |
1353 goto set_ixy; | 1365 goto set_ixy; |
1354 } | 1366 } |
1355 } | 1367 } |
1356 | 1368 |
1357 // AND | 1369 // AND |
1358 case 0xA6: // AND (IXY+disp) | 1370 case 0xA6: // AND (IXY+disp) |
1359 pc++; | 1371 pc++; |
1360 data = READ( ixy + (int8_t) data2 ); | 1372 data = READ( IXY_DISP( ixy, (int8_t) data2 ) ); |
1361 goto and_data; | 1373 goto and_data; |
1362 | 1374 |
1363 case 0xA4: // AND HXY | 1375 case 0xA4: // AND HXY |
1364 data = ixy >> 8; | 1376 data = ixy >> 8; |
1365 goto and_data; | 1377 goto and_data; |
1369 goto and_data; | 1381 goto and_data; |
1370 | 1382 |
1371 // OR | 1383 // OR |
1372 case 0xB6: // OR (IXY+disp) | 1384 case 0xB6: // OR (IXY+disp) |
1373 pc++; | 1385 pc++; |
1374 data = READ( ixy + (int8_t) data2 ); | 1386 data = READ( IXY_DISP( ixy, (int8_t) data2 ) ); |
1375 goto or_data; | 1387 goto or_data; |
1376 | 1388 |
1377 case 0xB4: // OR HXY | 1389 case 0xB4: // OR HXY |
1378 data = ixy >> 8; | 1390 data = ixy >> 8; |
1379 goto or_data; | 1391 goto or_data; |
1383 goto or_data; | 1395 goto or_data; |
1384 | 1396 |
1385 // XOR | 1397 // XOR |
1386 case 0xAE: // XOR (IXY+disp) | 1398 case 0xAE: // XOR (IXY+disp) |
1387 pc++; | 1399 pc++; |
1388 data = READ( ixy + (int8_t) data2 ); | 1400 data = READ( IXY_DISP( ixy, (int8_t) data2 ) ); |
1389 goto xor_data; | 1401 goto xor_data; |
1390 | 1402 |
1391 case 0xAC: // XOR HXY | 1403 case 0xAC: // XOR HXY |
1392 data = ixy >> 8; | 1404 data = ixy >> 8; |
1393 goto xor_data; | 1405 goto xor_data; |
1397 goto xor_data; | 1409 goto xor_data; |
1398 | 1410 |
1399 // CP | 1411 // CP |
1400 case 0xBE: // CP (IXY+disp) | 1412 case 0xBE: // CP (IXY+disp) |
1401 pc++; | 1413 pc++; |
1402 data = READ( ixy + (int8_t) data2 ); | 1414 data = READ( IXY_DISP( ixy, (int8_t) data2 ) ); |
1403 goto cp_data; | 1415 goto cp_data; |
1404 | 1416 |
1405 case 0xBC: // CP HXY | 1417 case 0xBC: // CP HXY |
1406 data = ixy >> 8; | 1418 data = ixy >> 8; |
1407 goto cp_data; | 1419 goto cp_data; |
1415 data = R8( data, 0x70 ); | 1427 data = R8( data, 0x70 ); |
1416 if ( 0 ) | 1428 if ( 0 ) |
1417 case 0x36: // LD (IXY+disp),imm | 1429 case 0x36: // LD (IXY+disp),imm |
1418 pc++, data = READ_PROG( pc ); | 1430 pc++, data = READ_PROG( pc ); |
1419 pc++; | 1431 pc++; |
1420 WRITE( ixy + (int8_t) data2, data ); | 1432 WRITE( IXY_DISP( ixy, (int8_t) data2 ), data ); |
1421 goto loop; | 1433 goto loop; |
1422 | 1434 |
1423 CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY | 1435 CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY |
1424 R8( data >> 3, 8 ) = ixy >> 8; | 1436 R8( data >> 3, 8 ) = ixy >> 8; |
1425 goto loop; | 1437 goto loop; |
1432 R8( data >> 3, 8 ) = ixy; | 1444 R8( data >> 3, 8 ) = ixy; |
1433 goto loop; | 1445 goto loop; |
1434 | 1446 |
1435 CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp) | 1447 CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp) |
1436 pc++; | 1448 pc++; |
1437 R8( data >> 3, 8 ) = READ( ixy + (int8_t) data2 ); | 1449 R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) ); |
1438 goto loop; | 1450 goto loop; |
1439 | 1451 |
1440 case 0x26: // LD HXY,imm | 1452 case 0x26: // LD HXY,imm |
1441 pc++; | 1453 pc++; |
1442 goto ld_hxy_data; | 1454 goto ld_hxy_data; |
1495 goto set_ixy; | 1507 goto set_ixy; |
1496 } | 1508 } |
1497 | 1509 |
1498 // DD/FD CB prefix | 1510 // DD/FD CB prefix |
1499 case 0xCB: { | 1511 case 0xCB: { |
1500 data = ixy + (int8_t) data2; | 1512 data = IXY_DISP( ixy, (int8_t) data2 ); |
1501 pc++; | 1513 pc++; |
1502 data2 = READ_PROG( pc ); | 1514 data2 = READ_PROG( pc ); |
1503 pc++; | 1515 pc++; |
1504 switch ( data2 ) | 1516 switch ( data2 ) |
1505 { | 1517 { |
1548 case 0x2B: // DEC IXY | 1560 case 0x2B: // DEC IXY |
1549 ixy = uint16_t (ixy - 1); | 1561 ixy = uint16_t (ixy - 1); |
1550 goto set_ixy; | 1562 goto set_ixy; |
1551 | 1563 |
1552 case 0x34: // INC (IXY+disp) | 1564 case 0x34: // INC (IXY+disp) |
1553 ixy += (int8_t) data2; | 1565 ixy = IXY_DISP( ixy, (int8_t) data2 ); |
1554 pc++; | 1566 pc++; |
1555 data = READ( ixy ) + 1; | 1567 data = READ( ixy ) + 1; |
1556 WRITE( ixy, data ); | 1568 WRITE( ixy, data ); |
1557 goto inc_set_flags; | 1569 goto inc_set_flags; |
1558 | 1570 |
1559 case 0x35: // DEC (IXY+disp) | 1571 case 0x35: // DEC (IXY+disp) |
1560 ixy += (int8_t) data2; | 1572 ixy = IXY_DISP( ixy, (int8_t) data2 ); |
1561 pc++; | 1573 pc++; |
1562 data = READ( ixy ) - 1; | 1574 data = READ( ixy ) - 1; |
1563 WRITE( ixy, data ); | 1575 WRITE( ixy, data ); |
1564 goto dec_set_flags; | 1576 goto dec_set_flags; |
1565 | 1577 |
1637 halt: | 1649 halt: |
1638 s_time &= 3; // increment by multiple of 4 | 1650 s_time &= 3; // increment by multiple of 4 |
1639 out_of_time: | 1651 out_of_time: |
1640 pc--; | 1652 pc--; |
1641 | 1653 |
1642 s.time = s_time; | 1654 s.time = s_time; |
1643 rg.flags = flags; | 1655 rg.flags = flags; |
1644 r.ix = ix; | 1656 r.ix = ix; |
1645 r.iy = iy; | 1657 r.iy = iy; |
1646 r.sp = sp; | 1658 r.sp = sp; |
1647 r.pc = pc; | 1659 r.pc = pc; |
1648 this->r.b = rg; | 1660 this->r.b = rg; |
1649 this->state_ = s; | 1661 this->state_ = s; |
1650 this->state = &this->state_; | 1662 this->state = &this->state_; |
1651 | 1663 |
1652 return warning; | 1664 return warning; |