From bbc6810018d4a02199d3907e6c20286ac3a42bf9 Mon Sep 17 00:00:00 2001 From: slack Date: Thu, 11 Jan 2007 01:33:56 +0000 Subject: [PATCH] Creado opcodes.h que contiene macros para implementar facilmente series de opcodes similares (p.e.: todos los LD A, reg) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Pasado el codigo existente a usar macros para evitar duplicacion innecesaria de codigo. Añadido ADC. git-svn-id: http://slack.codemaniacs.com/wenboi@2 0666ae3d-8926-0410-aeff-ae84559ff337 --- gbcore.cc | 433 ++++++++---------------------------------------------- opcodes.h | 81 ++++++++++ 2 files changed, 141 insertions(+), 373 deletions(-) create mode 100644 opcodes.h diff --git a/gbcore.cc b/gbcore.cc index 9ef4baa..252a63a 100644 --- a/gbcore.cc +++ b/gbcore.cc @@ -49,6 +49,7 @@ class GameBoy void set_flag(const u8 f) { regs.flags |= f; } void reset_flag(const u8 f) { regs.flags &= (~f); } + bool check_flag(const u8 f) { return (regs.flags & f != 0); } public: GameBoy(std::string rom_name); @@ -72,6 +73,7 @@ void GameBoy::reset() regs.PC = 0x100; } +#include "opcodes.h" void GameBoy::run_cycle() { @@ -87,230 +89,28 @@ void GameBoy::run_cycle() switch(opcode) { // LD n, nn - case 0x76: // LD A,n - regs.A = memory[regs.PC++]; - break; - case 0x06: // LD B,n - regs.B = memory[regs.PC++]; - break; - case 0x0E: // LD C,n - regs.C = memory[regs.PC++]; - break; - case 0x16: // LD D,n - regs.D = memory[regs.PC++]; - break; - case 0x1E: // LD E,n - regs.E = memory[regs.PC++]; - break; - case 0x26: // LD H,n - regs.H = memory[regs.PC++]; - break; - case 0x2E: // LD L,n - regs.L = memory[regs.PC++]; - break; + for_each_register(0x76, 0x06, 0x0E, 0x16, 0x1E, 0x26, 0x2E, LD_reg_nn) // LD r1,r2 - case 0x7F: // LD A,A - regs.A = regs.A; - break; - case 0x78: // LD A,B - regs.A = regs.B; - break; - case 0x79: // LD A,C - regs.A = regs.C; - break; - case 0x7A: // LD A,D - regs.A = regs.D; - break; - case 0x7B: // LD A,E - regs.A = regs.E; - break; - case 0x7C: // LD A,H - regs.A = regs.H; - break; - case 0x7D: // LD A,L - regs.A = regs.L; - break; - case 0x7E: // LD A,(HL) - regs.A = memory[regs.HL]; - break; - - case 0x47: // LD B,A - regs.B = regs.A; - break; - case 0x40: // LD B,B - regs.B = regs.B; - break; - case 0x41: // LD B,C - regs.B = regs.C; - break; - case 0x42: // LD B,D - regs.B = regs.D; - break; - case 0x43: // LD B,E - regs.B = regs.E; - break; - case 0x44: // LD B,H - regs.B = regs.H; - break; - case 0x45: // LD B,L - regs.B = regs.L; - break; - case 0x46: // LD B,(HL) - regs.B = memory[regs.HL]; - break; - - case 0x4F: // LD C,A - regs.C = regs.A; - break; - case 0x48: // LD C,B - regs.C = regs.B; - break; - case 0x49: // LD C,C - regs.C = regs.C; - break; - case 0x4A: // LD C,D - regs.C = regs.D; - break; - case 0x4B: // LD C,E - regs.C = regs.E; - break; - case 0x4C: // LD C,H - regs.C = regs.H; - break; - case 0x4D: // LD C,L - regs.C = regs.L; - break; - case 0x4E: // LD C,(HL) - regs.C = memory[regs.HL]; - break; - - case 0x57: // LD D,A - regs.D = regs.A; - break; - case 0x50: // LD D,B - regs.D = regs.B; - break; - case 0x51: // LD D,C - regs.D = regs.C; - break; - case 0x52: // LD D,D - regs.D = regs.D; - break; - case 0x53: // LD D,E - regs.D = regs.E; - break; - case 0x54: // LD D,H - regs.D = regs.H; - break; - case 0x55: // LD D,L - regs.D = regs.L; - break; - case 0x56: // LD D,(HL) - regs.D = memory[regs.HL]; - break; - - case 0x5F: // LD E,A - regs.E = regs.A; - break; - case 0x58: // LD E,B - regs.E = regs.D; - break; - case 0x59: // LD E,C - regs.E = regs.C; - break; - case 0x5A: // LD E,D - regs.E = regs.D; - break; - case 0x5B: // LD E,E - regs.E = regs.E; - break; - case 0x5C: // LD E,H - regs.E = regs.H; - break; - case 0x5D: // LD E,L - regs.E = regs.L; - break; - case 0x5E: // LD E,(HL) - regs.E = memory[regs.HL]; - break; - - case 0x67: // LD H,A - regs.H = regs.A; - break; - case 0x60: // LD H,B - regs.H = regs.B; - break; - case 0x61: // LD H,C - regs.H = regs.C; - break; - case 0x62: // LD H,D - regs.H = regs.D; - break; - case 0x63: // LD H,E - regs.H = regs.E; - break; - case 0x64: // LD H,H - regs.H = regs.H; - break; - case 0x65: // LD H,L - regs.H = regs.L; - break; - case 0x66: // LD H,(HL) - regs.H = memory[regs.HL]; - break; - - case 0x6F: // LD L,A - regs.L = regs.A; - break; - case 0x68: // LD L,B - regs.L = regs.D; - break; - case 0x69: // LD L,C - regs.L = regs.C; - break; - case 0x6A: // LD L,D - regs.L = regs.D; - break; - case 0x6B: // LD L,E - regs.L = regs.E; - break; - case 0x6C: // LD L,H - regs.L = regs.H; - break; - case 0x6D: // LD L,L - regs.L = regs.L; - break; - case 0x6E: // LD L,(HL) - regs.L = memory[regs.HL]; - break; + for_each_register(0x7F, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, LD_A_reg) + for_each_register(0x47, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, LD_B_reg) + for_each_register(0x4F, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, LD_C_reg) + for_each_register(0x57, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, LD_D_reg) + for_each_register(0x5F, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, LD_E_reg) + for_each_register(0x67, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, LD_H_reg) + for_each_register(0x6F, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, LD_L_reg) + + // LD reg, (HL) + for_each_register(0x7E, 0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, LD_reg__HL_) - case 0x77: // LD (HL),A - memory[regs.HL] = regs.A; - break; - case 0x70: // LD (HL),B - memory[regs.HL] = regs.B; - break; - case 0x71: // LD (HL),C - memory[regs.HL] = regs.C; - break; - case 0x72: // LD (HL),D - memory[regs.HL] = regs.D; - break; - case 0x73: // LD (HL),E - memory[regs.HL] = regs.E; - break; - case 0x74: // LD (HL),H - memory[regs.HL] = regs.H; - break; - case 0x75: // LD (HL),L - memory[regs.HL] = regs.L; - break; + // LD (HL), reg + for_each_register(0x77, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, LD__HL__reg) + case 0x36: // LD (HL), n memory[regs.HL] = memory[regs.PC++]; break; - // LD A, n + // LD A, mem case 0x0A: // LD A, (BC) regs.A = memory[regs.BC]; break; @@ -322,7 +122,7 @@ void GameBoy::run_cycle() regs.PC+=2; break; - // LD n, A + // LD mem, A case 0x02: // LD (BC), A memory[regs.BC] = regs.A; break; @@ -422,185 +222,71 @@ void GameBoy::run_cycle() } // PUSH nn - case 0xF5: // push AF - memory[regs.SP-1] = regs.A; - memory[regs.SP-2] = regs.flags; - regs.SP -= 2; - break; - case 0xC5: // push BC - memory[regs.SP-1] = regs.B; - memory[regs.SP-2] = regs.C; - regs.SP -= 2; - break; - case 0xD5: // push DE - memory[regs.SP-1] = regs.D; - memory[regs.SP-2] = regs.E; - regs.SP -= 2; - break; - case 0xE5: // push HL - memory[regs.SP-1] = regs.H; - memory[regs.SP-2] = regs.L; - regs.SP -= 2; - break; + PUSH(0xF5, A, flags) + PUSH(0xC5, B, C) + PUSH(0xD5, D, E) + PUSH(0xE5, H, L) // POP nn - case 0xF1: // pop AF - regs.flags = memory[regs.SP]; - regs.A = memory[regs.SP+1]; - regs.SP += 2; - break; - case 0xC1: // pop BC - regs.C = memory[regs.SP]; - regs.B = memory[regs.SP+1]; - regs.SP += 2; - break; - case 0xD1: // pop DE - regs.E = memory[regs.SP]; - regs.D = memory[regs.SP+1]; - regs.SP += 2; - break; - case 0xE1: // pop HL - regs.L = memory[regs.SP]; - regs.H = memory[regs.SP+1]; - regs.SP += 2; - break; + POP(0xF1, A, flags) + POP(0xC1, B, C) + POP(0xD1, D, E) + POP(0xE1, H, L) // 8-bit ALU - // ADD A, n - case 0x87: {// ADD A, A - int res = regs.A + regs.A; - int half_res = (regs.A & 0x0F) + (regs.A & 0x0F); - + // ADD A,reg + for_each_register(0x87, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, ADD_A_reg) + + case 0x86: {// ADD A, (HL) + int res = regs.A + memory[regs.HL]; + int half_res = (regs.A & 0x0F) + (memory[regs.HL] & 0x0F); regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); - reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); - break; - } - case 0x80: {// ADD A, B - int res = regs.A + regs.B; - int half_res = (regs.A & 0x0F) + (regs.B & 0x0F); - regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); + if (res > 0xFF) set_flag(CARRY_FLAG); + if (regs.A == 0) set_flag(ZERO_FLAG); + if (half_res > 0x0F) set_flag(HALF_CARRY_FLAG); break; } - case 0x81: {// ADD A, C - int res = regs.A + regs.C; - int half_res = (regs.A & 0x0F) + (regs.C & 0x0F); - + case 0xC6: {//ADD A, # + int inm = memory[regs.PC++]; + int res = regs.A + inm; + int half_res = (regs.A & 0x0F) + (inm & 0x0F); regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); - reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); - break; - } - case 0x82: {// ADD A, D - int res = regs.A + regs.D; - int half_res = (regs.A & 0x0F) + (regs.D & 0x0F); - regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); + if (res > 0xFF) set_flag(CARRY_FLAG); + if (regs.A == 0) set_flag(ZERO_FLAG); + if (half_res > 0x0F) set_flag(HALF_CARRY_FLAG); break; } - case 0x83: {// ADD A, E - int res = regs.A + regs.E; - int half_res = (regs.A & 0x0F) + (regs.E & 0x0F); - - regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); - reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); - break; - } - case 0x84: {// ADD A, H - int res = regs.A + regs.H; - int half_res = (regs.A & 0x0F) + (regs.H & 0x0F); - - regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); - reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); + // ADC A, n + for_each_register(0x8F, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, ADC_A_reg) - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); - break; - } - case 0x85: {// ADD A, L - int res = regs.A + regs.L; - int half_res = (regs.A & 0x0F) + (regs.L & 0x0F); - + case 0x8E: {// ADC A, (HL) + int carry = (check_flag(CARRY_FLAG)? 1 : 0); + int res = regs.A + memory[regs.HL] + carry; + int half_res = (regs.A & 0x0F) + (memory[regs.HL] & 0x0F) + carry; regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); - reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); - break; - } - case 0x86: {// ADD A, (HL) - int res = regs.A + memory[regs.HL]; - int half_res = (regs.A & 0x0F) + (memory[regs.HL] & 0x0F); - regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); + if (res > 0xFF) set_flag(CARRY_FLAG); + if (regs.A == 0) set_flag(ZERO_FLAG); + if (half_res > 0x0F) set_flag(HALF_CARRY_FLAG); break; } - case 0xC6: {//ADD A, # + case 0xCE: {//ADC A, # + int carry = (check_flag(CARRY_FLAG)? 1 : 0); int inm = memory[regs.PC++]; - int res = regs.A + inm; - int half_res = (regs.A & 0x0F) + (inm & 0x0F); - + int res = regs.A + inm + carry; + int half_res = (regs.A & 0x0F) + (inm & 0x0F) + carry; regs.A = static_cast(res); - if (res > 0xFF) - set_flag(CARRY_FLAG); + reset_flag(ADD_SUB_FLAG); - if (regs.A == 0) - set_flag(ZERO_FLAG); - - if (half_res > 0x0F) - set_flag(HALF_CARRY_FLAG); + if (res > 0xFF) set_flag(CARRY_FLAG); + if (regs.A == 0) set_flag(ZERO_FLAG); + if (half_res > 0x0F) set_flag(HALF_CARRY_FLAG); break; } @@ -608,6 +294,7 @@ void GameBoy::run_cycle() + diff --git a/opcodes.h b/opcodes.h new file mode 100644 index 0000000..6b13c41 --- /dev/null +++ b/opcodes.h @@ -0,0 +1,81 @@ +#define for_each_register(opA, opB, opC, opD, opE, opH, opL, macro) \ + macro(opA, A) \ + macro(opB, B) \ + macro(opC, C) \ + macro(opD, D) \ + macro(opE, E) \ + macro(opH, H) \ + macro(opL, L) + +#define LD_reg_nn(opcode, reg) \ + case opcode: \ + regs.reg = memory[regs.PC++]; \ + break; + +#define LD_reg_reg(opcode, reg1, reg2) \ + case opcode: \ + regs.reg1 = regs.reg2; \ + break; + +#define LD_A_reg(opcode, reg2) LD_reg_reg(opcode, A, reg2) +#define LD_B_reg(opcode, reg2) LD_reg_reg(opcode, B, reg2) +#define LD_C_reg(opcode, reg2) LD_reg_reg(opcode, C, reg2) +#define LD_D_reg(opcode, reg2) LD_reg_reg(opcode, D, reg2) +#define LD_E_reg(opcode, reg2) LD_reg_reg(opcode, E, reg2) +#define LD_H_reg(opcode, reg2) LD_reg_reg(opcode, H, reg2) +#define LD_L_reg(opcode, reg2) LD_reg_reg(opcode, L, reg2) + +// LD reg, (HL) +#define LD_reg__HL_(opcode, reg) \ + case opcode: \ + regs.reg = memory[regs.HL]; \ + break; + +// LD (HL), reg +#define LD__HL__reg(opcode, reg) \ + case opcode: \ + memory[regs.HL] = regs.reg; \ + break; + +#define PUSH(opcode, regH, regL) \ + case opcode: \ + memory[regs.SP-1] = regs.regH; \ + memory[regs.SP-2] = regs.regL; \ + regs.SP -= 2; \ + break; + +#define POP(opcode, regH, regL) \ + case opcode: \ + regs.regL = memory[regs.SP]; \ + regs.regH = memory[regs.SP+1]; \ + regs.SP += 2; \ + break; + +#define ADD_A_reg(opcode, reg) \ + case opcode: { \ + int res = regs.A + regs.reg; \ + int half_res = (regs.A & 0x0F) + (regs.reg & 0x0F); \ + regs.A = static_cast(res); \ + \ + reset_flag(ADD_SUB_FLAG); \ + if (res > 0xFF) set_flag(CARRY_FLAG); \ + if (regs.A == 0) set_flag(ZERO_FLAG); \ + if (half_res > 0x0F) set_flag(HALF_CARRY_FLAG); \ + break; \ + } + +#define ADC_A_reg(opcode, reg) \ + case opcode: { \ + int carry = (check_flag(CARRY_FLAG)? 1 : 0); \ + int res = regs.A + regs.reg + carry; \ + int half_res = (regs.A & 0x0F) + (regs.reg & 0x0F) + carry; \ + regs.A = static_cast(res); \ + \ + reset_flag(ADD_SUB_FLAG); \ + if (res > 0xFF) set_flag(CARRY_FLAG); \ + if (regs.A == 0) set_flag(ZERO_FLAG); \ + if (half_res > 0x0F) set_flag(HALF_CARRY_FLAG); \ + break; \ + } + + -- 2.34.1