added direct page indirect long addressing mode for operations that support it

This commit is contained in:
Preston Skupinski 2011-05-22 11:20:02 -04:00
parent 05f31579f1
commit c469f3f3ae
1 changed files with 195 additions and 78 deletions

273
cpu.js
View File

@ -54,6 +54,7 @@ function CPU_65816() {
0xa5 : LDA_direct_page, 0xbd : LDA_absolute_indexed_x,
0xb9 : LDA_absolute_indexed_y,
0xb2 : LDA_direct_page_indirect,
0xa7 : LDA_direct_page_indirect_long,
0xb1 : LDA_direct_page_indirect_indexed_y,
0xa3 : LDA_stack_relative,
0xb3 : LDA_stack_relative_indirect_indexed_y,
@ -67,6 +68,7 @@ function CPU_65816() {
0x8d : STA_absolute, 0x85 : STA_direct_page,
0x8f : STA_absolute_long,
0x92 : STA_direct_page_indirect,
0x87 : STA_direct_page_indirect_long,
0x91 : STA_direct_page_indirect_indexed_y,
0x9d : STA_absolute_indexed_x,
0x99 : STA_absolute_indexed_y,
@ -92,6 +94,7 @@ function CPU_65816() {
0x50 : BVC, 0x70 : BVS, 0x10 : BPL, 0x30 : BMI,
0x69 : ADC_const, 0x6d : ADC_absolute,
0x65 : ADC_direct_page, 0x72 : ADC_direct_page_indirect,
0x67 : ADC_direct_page_indirect_long,
0x71 : ADC_direct_page_indirect_indexed_y,
0x7d : ADC_absolute_indexed_x,
0x79 : ADC_absolute_indexed_y,
@ -101,6 +104,7 @@ function CPU_65816() {
0xe9 : SBC_const,
0xed : SBC_absolute, 0xe5 : SBC_direct_page,
0xf2 : SBC_direct_page_indirect,
0xe7 : SBC_direct_page_indirect_long,
0xf1 : SBC_direct_page_indirect_indexed_y,
0xfd : SBC_absolute_indexed_x,
0xf9 : SBC_absolute_indexed_y,
@ -109,6 +113,7 @@ function CPU_65816() {
0xf3 : SBC_stack_relative_indirect_indexed_y,
0xc9 : CMP_const, 0xc5 : CMP_direct_page,
0xcd : CMP_absolute, 0xd2 : CMP_direct_page_indirect,
0xc7 : CMP_direct_page_indirect_long,
0xd5 : CMP_direct_page_indexed_x,
0xdd : CMP_absolute_indexed_x,
0xd9 : CMP_absolute_indexed_y,
@ -121,6 +126,7 @@ function CPU_65816() {
0xc4 : CPY_direct_page, 0x29 : AND_const,
0x2d : AND_absolute, 0x25 : AND_direct_page,
0x32 : AND_direct_page_indirect,
0x27 : AND_direct_page_indirect_long,
0x31 : AND_direct_page_indirect_indexed_y,
0x3d : AND_absolute_indexed_x,
0x39 : AND_absolute_indexed_y,
@ -130,6 +136,7 @@ function CPU_65816() {
0x09 : ORA_const,
0x0d : ORA_absolute, 0x05 : ORA_direct_page,
0x12 : ORA_direct_page_indirect,
0x07 : ORA_direct_page_indirect_long,
0x11 : ORA_direct_page_indirect_indexed_y,
0x1d : ORA_absolute_indexed_x,
0x1f : ORA_absolute_indexed_y,
@ -139,6 +146,7 @@ function CPU_65816() {
0x49 : EOR_const, 0x4d : EOR_absolute,
0x45 : EOR_direct_page,
0x52 : EOR_direct_page_indirect,
0x47 : EOR_direct_page_indirect_long,
0x51 : EOR_direct_page_indirect_indexed_y,
0x5d : EOR_absolute_indexed_x,
0x59 : EOR_absolute_indexed_y,
@ -1328,6 +1336,26 @@ var EOR_direct_page_indirect = {
}
};
var EOR_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
if(cpu.p.e|cpu.p.m) {
EOR_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]);
} else {
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
EOR_const.execute(cpu, [low_byte, high_byte]);
}
}
};
var EOR_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -1534,6 +1562,26 @@ var ORA_direct_page_indirect = {
}
};
var ORA_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
if(cpu.p.e|cpu.p.m) {
ORA_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]);
} else {
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
ORA_const.execute(cpu, [low_byte, high_byte]);
}
}
};
var ORA_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -1740,6 +1788,26 @@ var AND_direct_page_indirect = {
}
};
var AND_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
if(cpu.p.e|cpu.p.m) {
AND_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]);
} else {
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
AND_const.execute(cpu, [low_byte, high_byte]);
}
}
};
var AND_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -2092,6 +2160,26 @@ var CMP_direct_page_indirect = {
}
};
var CMP_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
if(cpu.p.e|cpu.p.m) {
CMP_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]);
} else {
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
CMP_const.execute(cpu, [low_byte, high_byte]);
}
}
};
var CMP_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -2337,6 +2425,26 @@ var SBC_direct_page_indirect = {
}
};
var SBC_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
if(cpu.p.e|cpu.p.m) {
SBC_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]);
} else {
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
SBC_const.execute(cpu, [low_byte, high_byte]);
}
}
};
var SBC_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -2594,6 +2702,26 @@ var ADC_direct_page_indirect = {
}
};
var ADC_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
if(cpu.p.e|cpu.p.m) {
ADC_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]);
} else {
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
ADC_const.execute(cpu, [low_byte, high_byte]);
}
}
};
var ADC_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -3254,6 +3382,30 @@ var STA_direct_page_indirect = {
}
};
var STA_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
if(cpu.p.e|cpu.p.m) {
var low_byte_loc = cpu.mmu.read_byte(location);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
cpu.mmu.store_byte_long((high_byte_loc<<8) | low_byte_loc, bank_byte, cpu.r.a);
} else {
var low_byte_loc = cpu.mmu.read_byte(location);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
var low_byte = cpu.r.a & 0x00ff;
var high_byte = cpu.r.a >> 8;
cpu.mmu.store_byte(absolute_location, bank_byte, low_byte);
cpu.mmu.store_byte((absolute_location+1)&0xffff, bank_byte, high_byte);
}
}
};
var STA_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -3385,6 +3537,37 @@ var LDA_direct_page_indirect = {
}
};
var LDA_direct_page_indirect_long = {
bytes_required:function() {
return 2;
},
execute:function(cpu, bytes) {
var location = bytes[0] + cpu.r.d;
if(cpu.p.e|cpu.p.m) {
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
cpu.r.a = cpu.mmu.read_byte_long((high_byte_loc<<8) | low_byte_loc, bank_byte);
cpu.p.n = cpu.r.a >> 7;
} else {
var low_byte_loc = cpu.mmu.read_byte(location&0xffff);
var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff);
var bank_byte = cpu.mmu.read_byte((location+2)&0xffff);
var absolute_location = (high_byte_loc<<8) | low_byte_loc;
var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte);
var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte);
cpu.r.a = (high_byte<<8) | low_byte;
cpu.p.n = cpu.r.a >> 15;
}
if(cpu.r.a===0) {
cpu.p.z = 1;
} else {
cpu.p.z = 0;
}
}
};
var LDA_direct_page_indirect_indexed_y = {
bytes_required:function() {
return 2;
@ -3424,19 +3607,8 @@ var LDA_direct_page_indexed_x = {
cpu.r.a = cpu.mmu.read_byte(location);
cpu.p.n = cpu.r.a >> 7;
} else {
// Check for overflow.
var overflow_check = location - 0xffff;
if(overflow_check > 0) {
location = overflow_check-1;
}
var low_byte = cpu.mmu.read_byte(location);
// Check for potential overflow again.
if(location===0xffff) {
location = 0;
} else {
location++;
}
var high_byte = cpu.mmu.read_byte(location);
var low_byte = cpu.mmu.read_byte(location&0xffff);
var high_byte = cpu.mmu.read_byte((location+1)&0xffff);
cpu.r.a = low_byte | (high_byte<<8);
cpu.p.n = cpu.r.a >> 15;
}
@ -3635,19 +3807,8 @@ var LDY_direct_page_indexed_x = {
cpu.r.y = cpu.mmu.read_byte(location);
cpu.p.n = cpu.r.y >> 7;
} else {
// Check for overflow.
var overflow_check = location - 0xffff;
if(overflow_check > 0) {
location = overflow_check-1;
}
var low_byte = cpu.mmu.read_byte(location);
// Check for potential overflow again.
if(location===0xffff) {
location = 0;
} else {
location++;
}
var high_byte = cpu.mmu.read_byte(location);
var low_byte = cpu.mmu.read_byte(location&0xffff);
var high_byte = cpu.mmu.read_byte((location+1)&0xffff);
cpu.r.y = (high_byte<<8) | low_byte;
cpu.p.n = cpu.r.y >> 15;
}
@ -4044,19 +4205,8 @@ var STA_direct_page_indexed_x = {
} else {
var high_byte = cpu.r.a >> 8;
var low_byte = cpu.r.a & 0x00ff;
// Check for overflow.
var overflow_check = location - 0xffff;
if(overflow_check > 0) {
location = overflow_check-1;
}
cpu.mmu.store_byte(location, low_byte);
// Check for potential overflow again.
if(location===0xffff) {
location = 0;
} else {
location++;
}
cpu.mmu.store_byte(location, high_byte);
cpu.mmu.store_byte(location&0xffff, low_byte);
cpu.mmu.store_byte((location+1)&0xffff, high_byte);
}
}
};
@ -4123,19 +4273,8 @@ var STY_direct_page_indexed_x = {
} else {
var high_byte = cpu.r.y >> 8;
var low_byte = cpu.r.y & 0x00ff;
// Check for overflow.
var overflow_check = location - 0xffff;
if(overflow_check > 0) {
location = overflow_check-1;
}
cpu.mmu.store_byte(location, low_byte);
// Check for potential overflow again.
if(location===0xffff) {
location = 0;
} else {
location++;
}
cpu.mmu.store_byte(location, high_byte);
cpu.mmu.store_byte(location&0xffff, low_byte);
cpu.mmu.store_byte((location+1)&0xffff, high_byte);
}
}
};
@ -4185,19 +4324,8 @@ var STX_direct_page_indexed_y = {
} else {
var high_byte = cpu.r.x >> 8;
var low_byte = cpu.r.x & 0x00ff;
// Check for overflow.
var overflow_check = location - 0xffff;
if(overflow_check > 0) {
location = overflow_check-1;
}
cpu.mmu.store_byte(location, low_byte);
// Check for potential overflow again.
if(location===0xffff) {
location = 0;
} else {
location++;
}
cpu.mmu.store_byte(location, high_byte);
cpu.mmu.store_byte(location&0xffff, low_byte);
cpu.mmu.store_byte((location+1)&0xffff, high_byte);
}
}
};
@ -4303,19 +4431,8 @@ var LDX_direct_page_indexed_y = {
cpu.r.x = cpu.mmu.read_byte(location);
cpu.p.n = cpu.r.x >> 7;
} else {
// Check for overflow.
var overflow_check = location - 0xffff;
if(overflow_check > 0) {
location = overflow_check-1;
}
var low_byte = cpu.mmu.read_byte(location);
// Check for potential overflow again.
if(location===0xffff) {
location = 0;
} else {
location++;
}
var high_byte = cpu.mmu.read_byte(location);
var low_byte = cpu.mmu.read_byte(location&0xffff);
var high_byte = cpu.mmu.read_byte((location+1)&0xffff);
cpu.r.x = (high_byte<<8) | low_byte;
cpu.p.n = cpu.r.x >> 15;
}