psx emulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.0 KiB

2 years ago
2 years ago
2 years ago
2 years ago
  1. #include "insn.h"
  2. #include <stddef.h>
  3. #include <stdio.h>
  4. #include "cpu.h"
  5. #include "log.h"
  6. #define TABLE_SIZE 0x34
  7. #define BITS(x, start, len) (((x) >> (start)) & ((1 << (len)) - 1))
  8. #define OP(insn) BITS(insn, 26, 6)
  9. #define RS(insn) BITS(insn, 21, 5)
  10. #define RT(insn) BITS(insn, 16, 5)
  11. #define RD(insn) BITS(insn, 11, 5)
  12. #define COMMENT(insn) BITS(insn, 6, 20)
  13. #define IMM5(insn) BITS(insn, 6, 5)
  14. #define OP2(insn) BITS(insn, 0, 6)
  15. #define IMM(insn) BITS(insn, 0, 16)
  16. static cpu_insn_handler primary_insn_handler[TABLE_SIZE];
  17. static cpu_insn_handler secondary_insn_handler[TABLE_SIZE];
  18. void insn_execute(cpu_t *cpu, uint32_t insn) {
  19. const op_primary_t op = OP(insn);
  20. if (op == SPECIAL) {
  21. const op_secondary_t op2 = OP2(insn);
  22. if (op2 > TABLE_SIZE || secondary_insn_handler[op2] == NULL) {
  23. fatal("Unsupported instruction: insn=%08x, op=%02x, op2=%02x", insn,
  24. op, op2);
  25. }
  26. secondary_insn_handler[op2](cpu, insn);
  27. return;
  28. }
  29. if (op > TABLE_SIZE || primary_insn_handler[op] == NULL) {
  30. fatal("Unsupported instruction: insn=%08x, op=%02x", insn, op);
  31. }
  32. primary_insn_handler[op](cpu, insn);
  33. }
  34. void insn_lw(cpu_t *cpu, uint32_t insn) {
  35. const uint8_t rt = RT(insn);
  36. const uint8_t rs = RS(insn);
  37. const uint16_t imm = IMM(insn);
  38. debug("LW %s, [%s + %x]", REG_NAMES[rt], REG_NAMES[rs], imm);
  39. cpu->regs[rt] = cpu_read32(cpu, cpu->regs[rs] + imm);
  40. }
  41. void insn_srl(cpu_t *cpu, uint32_t insn) {
  42. const uint8_t rd = RD(insn);
  43. const uint8_t rt = RT(insn);
  44. const uint8_t imm5 = IMM5(insn);
  45. debug("SRL %s, %s, %u", REG_NAMES[rd], REG_NAMES[rt], imm5);
  46. cpu->regs[rd] = cpu->regs[rt] >> imm5;
  47. }
  48. void insn_addu(cpu_t *cpu, uint32_t insn) {
  49. const uint8_t rd = RD(insn);
  50. const uint8_t rs = RS(insn);
  51. const uint8_t rt = RT(insn);
  52. debug("ADDU %s, %s, %s", REG_NAMES[rd], REG_NAMES[rs], REG_NAMES[rt]);
  53. cpu->regs[rd] = cpu->regs[rs] + cpu->regs[rt];
  54. }
  55. void insn_addiu(cpu_t *cpu, uint32_t insn) {
  56. const uint8_t rt = RT(insn);
  57. const uint8_t rs = RS(insn);
  58. const int16_t imm = (int16_t)IMM(insn);
  59. debug("ADDIU %s, %s, %x", REG_NAMES[rt], REG_NAMES[rs], imm);
  60. cpu->regs[rt] = cpu->regs[rs] + imm;
  61. }
  62. void insn_sw(cpu_t *cpu, uint32_t insn) {
  63. const uint8_t rt = RT(insn);
  64. const uint8_t rs = RS(insn);
  65. const uint16_t imm = IMM(insn);
  66. debug("SW %s, [%s + %x]", REG_NAMES[rt], REG_NAMES[rt], imm);
  67. cpu_write32(cpu, cpu->regs[rt], imm + cpu->regs[rs]);
  68. }
  69. void insn_sll(cpu_t *cpu, uint32_t insn) {
  70. const uint8_t rd = RD(insn);
  71. const uint8_t rt = RT(insn);
  72. const uint8_t imm5 = IMM5(insn);
  73. debug("SLL %s, %s, %u", REG_NAMES[rd], REG_NAMES[rt], imm5);
  74. cpu->regs[rd] = cpu->regs[rt] << imm5;
  75. }
  76. static cpu_insn_handler primary_insn_handler[TABLE_SIZE] = {
  77. [LW] = insn_lw,
  78. [ADDIU] = insn_addiu,
  79. [SW] = insn_sw,
  80. };
  81. static cpu_insn_handler secondary_insn_handler[TABLE_SIZE] = {
  82. [SLL] = insn_sll,
  83. [ADDU] = insn_addu,
  84. [SRL] = insn_srl,
  85. };