From c469f3f3ae047a7b8269183c88ebbacbe331a061 Mon Sep 17 00:00:00 2001 From: Preston Skupinski Date: Sun, 22 May 2011 11:20:02 -0400 Subject: [PATCH] added direct page indirect long addressing mode for operations that support it --- cpu.js | 273 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 195 insertions(+), 78 deletions(-) diff --git a/cpu.js b/cpu.js index 7b51b5d..1db6758 100644 --- a/cpu.js +++ b/cpu.js @@ -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; }