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;