Add __CYCLES__ variable to count cycles used by instructions (#2171)

This commit is contained in:
Rangi authored and GitHub committed 2026-09-27 19:59:32 -04:00
1 parent 6e2e2f1db7
commit 62a9d8d518
7 files changed
+192

No files matched your search

+1
View File
@@ -40,6 +40,7 @@ struct Section {
uint16_t alignOfs; uint16_t alignOfs;
std::deque<Patch> patches; std::deque<Patch> patches;
std::vector<uint8_t> data; std::vector<uint8_t> data;
uint32_t cyclesCounter; // `__CYCLES__` value; unsigned for well-defined overflow on increment
SectionTypeInfo const &typeInfo() const { return sectionTypeInfo[type]; } SectionTypeInfo const &typeInfo() const { return sectionTypeInfo[type]; }
+1
View File
@@ -83,6 +83,7 @@ Symbol *sym_RedefEqu(InternedStr symName, int32_t value);
Symbol *sym_AddVar(InternedStr symName, int32_t value); Symbol *sym_AddVar(InternedStr symName, int32_t value);
int32_t sym_GetRSValue(); int32_t sym_GetRSValue();
void sym_SetRSValue(int32_t value); void sym_SetRSValue(int32_t value);
void sym_IncrementCYCLESValue(uint32_t delta);
// Find a symbol by exact name, bypassing expansion checks // Find a symbol by exact name, bypassing expansion checks
Symbol *sym_FindExactSymbol(InternedStr symName); Symbol *sym_FindExactSymbol(InternedStr symName);
// Find a symbol, possibly scoped, by name // Find a symbol, possibly scoped, by name
+1
View File
@@ -1800,6 +1800,7 @@ The following symbols are defined by the assembler:
.It Dv . Ta Ic EQUS Ta The current global label scope .It Dv . Ta Ic EQUS Ta The current global label scope
.It Dv .. Ta Ic EQUS Ta The current local label scope .It Dv .. Ta Ic EQUS Ta The current local label scope
.It Dv __SCOPE__ Ta Ic EQUS Ta The innermost current label scope level (empty, ".", or "..") .It Dv __SCOPE__ Ta Ic EQUS Ta The innermost current label scope level (empty, ".", or "..")
.It Dv __CYCLES__ Ta Ic = Ta Number of M-cycles used by instructions in the current section
.It Dv _RS Ta Ic = Ta _RS Counter .It Dv _RS Ta Ic = Ta _RS Counter
.It Dv _NARG Ta Ic EQU Ta Number of arguments passed to macro, updated by Ic SHIFT .It Dv _NARG Ta Ic EQU Ta Number of arguments passed to macro, updated by Ic SHIFT
.It Dv __ISO_8601_LOCAL__ Ta Ic EQUS Ta ISO 8601 timestamp (local) .It Dv __ISO_8601_LOCAL__ Ta Ic EQUS Ta ISO 8601 timestamp (local)
+87
View File
@@ -1904,9 +1904,11 @@ sm83_adc:
SM83_ADC op_a_n { SM83_ADC op_a_n {
sect_ConstByte(0xCE); sect_ConstByte(0xCE);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_ADC op_a_r { | SM83_ADC op_a_r {
sect_ConstByte(0x88 | $2); sect_ConstByte(0x88 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
@@ -1914,16 +1916,20 @@ sm83_add:
SM83_ADD op_a_n { SM83_ADD op_a_n {
sect_ConstByte(0xC6); sect_ConstByte(0xC6);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_ADD op_a_r { | SM83_ADD op_a_r {
sect_ConstByte(0x80 | $2); sect_ConstByte(0x80 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
| SM83_ADD MODE_HL COMMA reg_ss { | SM83_ADD MODE_HL COMMA reg_ss {
sect_ConstByte(0x09 | ($4 << 4)); sect_ConstByte(0x09 | ($4 << 4));
sym_IncrementCYCLESValue(2);
} }
| SM83_ADD MODE_SP COMMA reloc_8bit_signed { | SM83_ADD MODE_SP COMMA reloc_8bit_signed {
sect_ConstByte(0xE8); sect_ConstByte(0xE8);
sect_RelByte($4, 1); sect_RelByte($4, 1);
sym_IncrementCYCLESValue(4);
} }
; ;
@@ -1931,9 +1937,11 @@ sm83_and:
SM83_AND op_a_n { SM83_AND op_a_n {
sect_ConstByte(0xE6); sect_ConstByte(0xE6);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_AND op_a_r { | SM83_AND op_a_r {
sect_ConstByte(0xA0 | $2); sect_ConstByte(0xA0 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
@@ -1947,6 +1955,7 @@ sm83_bit:
} else { } else {
sect_ConstByte(mask | ($2.value() << 3)); sect_ConstByte(mask | ($2.value() << 3));
} }
sym_IncrementCYCLESValue($4 == REG_HL_IND ? 3 : 2);
} }
; ;
@@ -1954,16 +1963,19 @@ sm83_call:
SM83_CALL reloc_16bit { SM83_CALL reloc_16bit {
sect_ConstByte(0xCD); sect_ConstByte(0xCD);
sect_RelWord($2, 1); sect_RelWord($2, 1);
sym_IncrementCYCLESValue(6);
} }
| SM83_CALL ccode_expr COMMA reloc_16bit { | SM83_CALL ccode_expr COMMA reloc_16bit {
sect_ConstByte(0xC4 | ($2 << 3)); sect_ConstByte(0xC4 | ($2 << 3));
sect_RelWord($4, 1); sect_RelWord($4, 1);
sym_IncrementCYCLESValue(6);
} }
; ;
sm83_ccf: sm83_ccf:
SM83_CCF { SM83_CCF {
sect_ConstByte(0x3F); sect_ConstByte(0x3F);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -1971,60 +1983,72 @@ sm83_cp:
SM83_CP op_a_n { SM83_CP op_a_n {
sect_ConstByte(0xFE); sect_ConstByte(0xFE);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_CP op_a_r { | SM83_CP op_a_r {
sect_ConstByte(0xB8 | $2); sect_ConstByte(0xB8 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
sm83_cpl: sm83_cpl:
SM83_CPL { SM83_CPL {
sect_ConstByte(0x2F); sect_ConstByte(0x2F);
sym_IncrementCYCLESValue(1);
} }
| SM83_CPL MODE_A { | SM83_CPL MODE_A {
sect_ConstByte(0x2F); sect_ConstByte(0x2F);
sym_IncrementCYCLESValue(1);
} }
; ;
sm83_daa: sm83_daa:
SM83_DAA { SM83_DAA {
sect_ConstByte(0x27); sect_ConstByte(0x27);
sym_IncrementCYCLESValue(1);
} }
; ;
sm83_dec: sm83_dec:
SM83_DEC reg_r { SM83_DEC reg_r {
sect_ConstByte(0x05 | ($2 << 3)); sect_ConstByte(0x05 | ($2 << 3));
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 3 : 1);
} }
| SM83_DEC reg_ss { | SM83_DEC reg_ss {
sect_ConstByte(0x0B | ($2 << 4)); sect_ConstByte(0x0B | ($2 << 4));
sym_IncrementCYCLESValue(2);
} }
; ;
sm83_di: sm83_di:
SM83_DI { SM83_DI {
sect_ConstByte(0xF3); sect_ConstByte(0xF3);
sym_IncrementCYCLESValue(1);
} }
; ;
sm83_ei: sm83_ei:
SM83_EI { SM83_EI {
sect_ConstByte(0xFB); sect_ConstByte(0xFB);
sym_IncrementCYCLESValue(1);
} }
; ;
sm83_halt: sm83_halt:
SM83_HALT { SM83_HALT {
sect_ConstByte(0x76); sect_ConstByte(0x76);
sym_IncrementCYCLESValue(1);
} }
; ;
sm83_inc: sm83_inc:
SM83_INC reg_r { SM83_INC reg_r {
sect_ConstByte(0x04 | ($2 << 3)); sect_ConstByte(0x04 | ($2 << 3));
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 3 : 1);
} }
| SM83_INC reg_ss { | SM83_INC reg_ss {
sect_ConstByte(0x03 | ($2 << 4)); sect_ConstByte(0x03 | ($2 << 4));
sym_IncrementCYCLESValue(2);
} }
; ;
@@ -2032,13 +2056,16 @@ sm83_jp:
SM83_JP reloc_16bit { SM83_JP reloc_16bit {
sect_ConstByte(0xC3); sect_ConstByte(0xC3);
sect_RelWord($2, 1); sect_RelWord($2, 1);
sym_IncrementCYCLESValue(4);
} }
| SM83_JP ccode_expr COMMA reloc_16bit { | SM83_JP ccode_expr COMMA reloc_16bit {
sect_ConstByte(0xC2 | ($2 << 3)); sect_ConstByte(0xC2 | ($2 << 3));
sect_RelWord($4, 1); sect_RelWord($4, 1);
sym_IncrementCYCLESValue(4);
} }
| SM83_JP MODE_HL { | SM83_JP MODE_HL {
sect_ConstByte(0xE9); sect_ConstByte(0xE9);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2046,28 +2073,34 @@ sm83_jr:
SM83_JR reloc_16bit { SM83_JR reloc_16bit {
sect_ConstByte(0x18); sect_ConstByte(0x18);
sect_PCRelByte($2, 1); sect_PCRelByte($2, 1);
sym_IncrementCYCLESValue(3);
} }
| SM83_JR ccode_expr COMMA reloc_16bit { | SM83_JR ccode_expr COMMA reloc_16bit {
sect_ConstByte(0x20 | ($2 << 3)); sect_ConstByte(0x20 | ($2 << 3));
sect_PCRelByte($4, 1); sect_PCRelByte($4, 1);
sym_IncrementCYCLESValue(3);
} }
; ;
sm83_ldi: sm83_ldi:
SM83_LDI LBRACK MODE_HL RBRACK COMMA MODE_A { SM83_LDI LBRACK MODE_HL RBRACK COMMA MODE_A {
sect_ConstByte(0x02 | (2 << 4)); sect_ConstByte(0x02 | (2 << 4));
sym_IncrementCYCLESValue(2);
} }
| SM83_LDI MODE_A COMMA LBRACK MODE_HL RBRACK { | SM83_LDI MODE_A COMMA LBRACK MODE_HL RBRACK {
sect_ConstByte(0x0A | (2 << 4)); sect_ConstByte(0x0A | (2 << 4));
sym_IncrementCYCLESValue(2);
} }
; ;
sm83_ldd: sm83_ldd:
SM83_LDD LBRACK MODE_HL RBRACK COMMA MODE_A { SM83_LDD LBRACK MODE_HL RBRACK COMMA MODE_A {
sect_ConstByte(0x02 | (3 << 4)); sect_ConstByte(0x02 | (3 << 4));
sym_IncrementCYCLESValue(2);
} }
| SM83_LDD MODE_A COMMA LBRACK MODE_HL RBRACK { | SM83_LDD MODE_A COMMA LBRACK MODE_HL RBRACK {
sect_ConstByte(0x0A | (3 << 4)); sect_ConstByte(0x0A | (3 << 4));
sym_IncrementCYCLESValue(2);
} }
; ;
@@ -2080,6 +2113,7 @@ sm83_ldh:
} else { } else {
sect_ConstByte($4.value()); sect_ConstByte($4.value());
} }
sym_IncrementCYCLESValue(3);
} }
| SM83_LDH op_mem_ind COMMA MODE_A { | SM83_LDH op_mem_ind COMMA MODE_A {
$2.addCheckHRAM(); $2.addCheckHRAM();
@@ -2089,18 +2123,23 @@ sm83_ldh:
} else { } else {
sect_ConstByte($2.value()); sect_ConstByte($2.value());
} }
sym_IncrementCYCLESValue(3);
} }
| SM83_LDH MODE_A COMMA c_ind { | SM83_LDH MODE_A COMMA c_ind {
sect_ConstByte(0xF2); sect_ConstByte(0xF2);
sym_IncrementCYCLESValue(2);
} }
| SM83_LDH MODE_A COMMA ff00_c_ind { | SM83_LDH MODE_A COMMA ff00_c_ind {
sect_ConstByte(0xF2); sect_ConstByte(0xF2);
sym_IncrementCYCLESValue(2);
} }
| SM83_LDH c_ind COMMA MODE_A { | SM83_LDH c_ind COMMA MODE_A {
sect_ConstByte(0xE2); sect_ConstByte(0xE2);
sym_IncrementCYCLESValue(2);
} }
| SM83_LDH ff00_c_ind COMMA MODE_A { | SM83_LDH ff00_c_ind COMMA MODE_A {
sect_ConstByte(0xE2); sect_ConstByte(0xE2);
sym_IncrementCYCLESValue(2);
} }
; ;
@@ -2130,10 +2169,12 @@ sm83_ld_hl:
SM83_LD MODE_HL COMMA MODE_SP op_sp_offset { SM83_LD MODE_HL COMMA MODE_SP op_sp_offset {
sect_ConstByte(0xF8); sect_ConstByte(0xF8);
sect_RelByte($5, 1); sect_RelByte($5, 1);
sym_IncrementCYCLESValue(3);
} }
| SM83_LD MODE_HL COMMA reloc_16bit { | SM83_LD MODE_HL COMMA reloc_16bit {
sect_ConstByte(0x01 | (REG_HL << 4)); sect_ConstByte(0x01 | (REG_HL << 4));
sect_RelWord($4, 1); sect_RelWord($4, 1);
sym_IncrementCYCLESValue(3);
} }
| SM83_LD MODE_HL COMMA reg_tt_no_af { | SM83_LD MODE_HL COMMA reg_tt_no_af {
::error( ::error(
@@ -2148,6 +2189,7 @@ sm83_ld_hl:
sm83_ld_sp: sm83_ld_sp:
SM83_LD MODE_SP COMMA MODE_HL { SM83_LD MODE_SP COMMA MODE_HL {
sect_ConstByte(0xF9); sect_ConstByte(0xF9);
sym_IncrementCYCLESValue(2);
} }
| SM83_LD MODE_SP COMMA reg_bc_or_de { | SM83_LD MODE_SP COMMA reg_bc_or_de {
::error("\"LD SP, %s\" is not a valid instruction", reg_tt_names[$4]); ::error("\"LD SP, %s\" is not a valid instruction", reg_tt_names[$4]);
@@ -2155,6 +2197,7 @@ sm83_ld_sp:
| SM83_LD MODE_SP COMMA reloc_16bit { | SM83_LD MODE_SP COMMA reloc_16bit {
sect_ConstByte(0x01 | (REG_SP << 4)); sect_ConstByte(0x01 | (REG_SP << 4));
sect_RelWord($4, 1); sect_RelWord($4, 1);
sym_IncrementCYCLESValue(3);
} }
; ;
@@ -2162,22 +2205,26 @@ sm83_ld_mem:
SM83_LD op_mem_ind COMMA MODE_SP { SM83_LD op_mem_ind COMMA MODE_SP {
sect_ConstByte(0x08); sect_ConstByte(0x08);
sect_RelWord($2, 1); sect_RelWord($2, 1);
sym_IncrementCYCLESValue(5);
} }
| SM83_LD op_mem_ind COMMA MODE_A { | SM83_LD op_mem_ind COMMA MODE_A {
sect_ConstByte(0xEA); sect_ConstByte(0xEA);
sect_RelWord($2, 1); sect_RelWord($2, 1);
sym_IncrementCYCLESValue(4);
} }
; ;
sm83_ld_c_ind: sm83_ld_c_ind:
SM83_LD ff00_c_ind COMMA MODE_A { SM83_LD ff00_c_ind COMMA MODE_A {
sect_ConstByte(0xE2); sect_ConstByte(0xE2);
sym_IncrementCYCLESValue(2);
} }
; ;
sm83_ld_rr: sm83_ld_rr:
SM83_LD reg_rr COMMA MODE_A { SM83_LD reg_rr COMMA MODE_A {
sect_ConstByte(0x02 | ($2 << 4)); sect_ConstByte(0x02 | ($2 << 4));
sym_IncrementCYCLESValue(2);
} }
; ;
@@ -2185,12 +2232,14 @@ sm83_ld_r_no_a:
SM83_LD reg_r_no_a COMMA reloc_8bit { SM83_LD reg_r_no_a COMMA reloc_8bit {
sect_ConstByte(0x06 | ($2 << 3)); sect_ConstByte(0x06 | ($2 << 3));
sect_RelByte($4, 1); sect_RelByte($4, 1);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 3 : 2);
} }
| SM83_LD reg_r_no_a COMMA reg_r { | SM83_LD reg_r_no_a COMMA reg_r {
if ($2 == REG_HL_IND && $4 == REG_HL_IND) { if ($2 == REG_HL_IND && $4 == REG_HL_IND) {
::error("\"LD [HL], [HL]\" is not a valid instruction"); ::error("\"LD [HL], [HL]\" is not a valid instruction");
} else { } else {
sect_ConstByte(0x40 | ($2 << 3) | $4); sect_ConstByte(0x40 | ($2 << 3) | $4);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
} }
; ;
@@ -2199,19 +2248,24 @@ sm83_ld_a:
SM83_LD reg_a COMMA reloc_8bit { SM83_LD reg_a COMMA reloc_8bit {
sect_ConstByte(0x06 | ($2 << 3)); sect_ConstByte(0x06 | ($2 << 3));
sect_RelByte($4, 1); sect_RelByte($4, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_LD reg_a COMMA reg_r { | SM83_LD reg_a COMMA reg_r {
sect_ConstByte(0x40 | ($2 << 3) | $4); sect_ConstByte(0x40 | ($2 << 3) | $4);
sym_IncrementCYCLESValue($4 == REG_HL_IND ? 2 : 1);
} }
| SM83_LD reg_a COMMA ff00_c_ind { | SM83_LD reg_a COMMA ff00_c_ind {
sect_ConstByte(0xF2); sect_ConstByte(0xF2);
sym_IncrementCYCLESValue(2);
} }
| SM83_LD reg_a COMMA reg_rr { | SM83_LD reg_a COMMA reg_rr {
sect_ConstByte(0x0A | ($4 << 4)); sect_ConstByte(0x0A | ($4 << 4));
sym_IncrementCYCLESValue(2);
} }
| SM83_LD reg_a COMMA op_mem_ind { | SM83_LD reg_a COMMA op_mem_ind {
sect_ConstByte(0xFA); sect_ConstByte(0xFA);
sect_RelWord($4, 1); sect_RelWord($4, 1);
sym_IncrementCYCLESValue(4);
} }
; ;
@@ -2219,6 +2273,7 @@ sm83_ld_ss:
SM83_LD reg_bc_or_de COMMA reloc_16bit { SM83_LD reg_bc_or_de COMMA reloc_16bit {
sect_ConstByte(0x01 | ($2 << 4)); sect_ConstByte(0x01 | ($2 << 4));
sect_RelWord($4, 1); sect_RelWord($4, 1);
sym_IncrementCYCLESValue(3);
} }
| SM83_LD reg_bc_or_de COMMA reg_tt_no_af { | SM83_LD reg_bc_or_de COMMA reg_tt_no_af {
::error( ::error(
@@ -2238,6 +2293,7 @@ sm83_ld_ss:
sm83_nop: sm83_nop:
SM83_NOP { SM83_NOP {
sect_ConstByte(0x00); sect_ConstByte(0x00);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2245,21 +2301,25 @@ sm83_or:
SM83_OR op_a_n { SM83_OR op_a_n {
sect_ConstByte(0xF6); sect_ConstByte(0xF6);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_OR op_a_r { | SM83_OR op_a_r {
sect_ConstByte(0xB0 | $2); sect_ConstByte(0xB0 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
sm83_pop: sm83_pop:
SM83_POP reg_tt { SM83_POP reg_tt {
sect_ConstByte(0xC1 | ($2 << 4)); sect_ConstByte(0xC1 | ($2 << 4));
sym_IncrementCYCLESValue(3);
} }
; ;
sm83_push: sm83_push:
SM83_PUSH reg_tt { SM83_PUSH reg_tt {
sect_ConstByte(0xC5 | ($2 << 4)); sect_ConstByte(0xC5 | ($2 << 4));
sym_IncrementCYCLESValue(4);
} }
; ;
@@ -2273,21 +2333,25 @@ sm83_res:
} else { } else {
sect_ConstByte(mask | ($2.value() << 3)); sect_ConstByte(mask | ($2.value() << 3));
} }
sym_IncrementCYCLESValue($4 == REG_HL_IND ? 4 : 2);
} }
; ;
sm83_ret: sm83_ret:
SM83_RET { SM83_RET {
sect_ConstByte(0xC9); sect_ConstByte(0xC9);
sym_IncrementCYCLESValue(4);
} }
| SM83_RET ccode_expr { | SM83_RET ccode_expr {
sect_ConstByte(0xC0 | ($2 << 3)); sect_ConstByte(0xC0 | ($2 << 3));
sym_IncrementCYCLESValue(5);
} }
; ;
sm83_reti: sm83_reti:
SM83_RETI { SM83_RETI {
sect_ConstByte(0xD9); sect_ConstByte(0xD9);
sym_IncrementCYCLESValue(4);
} }
; ;
@@ -2295,12 +2359,14 @@ sm83_rl:
SM83_RL reg_r { SM83_RL reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x10 | $2); sect_ConstByte(0x10 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
sm83_rla: sm83_rla:
SM83_RLA { SM83_RLA {
sect_ConstByte(0x17); sect_ConstByte(0x17);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2308,12 +2374,14 @@ sm83_rlc:
SM83_RLC reg_r { SM83_RLC reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x00 | $2); sect_ConstByte(0x00 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
sm83_rlca: sm83_rlca:
SM83_RLCA { SM83_RLCA {
sect_ConstByte(0x07); sect_ConstByte(0x07);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2321,12 +2389,14 @@ sm83_rr:
SM83_RR reg_r { SM83_RR reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x18 | $2); sect_ConstByte(0x18 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
sm83_rra: sm83_rra:
SM83_RRA { SM83_RRA {
sect_ConstByte(0x1F); sect_ConstByte(0x1F);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2334,12 +2404,14 @@ sm83_rrc:
SM83_RRC reg_r { SM83_RRC reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x08 | $2); sect_ConstByte(0x08 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
sm83_rrca: sm83_rrca:
SM83_RRCA { SM83_RRCA {
sect_ConstByte(0x0F); sect_ConstByte(0x0F);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2351,6 +2423,7 @@ sm83_rst:
} else { } else {
sect_ConstByte(0xC7 | $2.value()); sect_ConstByte(0xC7 | $2.value());
} }
sym_IncrementCYCLESValue(4);
} }
; ;
@@ -2358,15 +2431,18 @@ sm83_sbc:
SM83_SBC op_a_n { SM83_SBC op_a_n {
sect_ConstByte(0xDE); sect_ConstByte(0xDE);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_SBC op_a_r { | SM83_SBC op_a_r {
sect_ConstByte(0x98 | $2); sect_ConstByte(0x98 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
sm83_scf: sm83_scf:
SM83_SCF { SM83_SCF {
sect_ConstByte(0x37); sect_ConstByte(0x37);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2380,6 +2456,7 @@ sm83_set:
} else { } else {
sect_ConstByte(mask | ($2.value() << 3)); sect_ConstByte(mask | ($2.value() << 3));
} }
sym_IncrementCYCLESValue($4 == REG_HL_IND ? 4 : 2);
} }
; ;
@@ -2387,6 +2464,7 @@ sm83_sla:
SM83_SLA reg_r { SM83_SLA reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x20 | $2); sect_ConstByte(0x20 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
@@ -2394,6 +2472,7 @@ sm83_sra:
SM83_SRA reg_r { SM83_SRA reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x28 | $2); sect_ConstByte(0x28 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
@@ -2401,6 +2480,7 @@ sm83_srl:
SM83_SRL reg_r { SM83_SRL reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x38 | $2); sect_ConstByte(0x38 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
@@ -2408,10 +2488,12 @@ sm83_stop:
SM83_STOP { SM83_STOP {
sect_ConstByte(0x10); sect_ConstByte(0x10);
sect_ConstByte(0x00); sect_ConstByte(0x00);
sym_IncrementCYCLESValue(1);
} }
| SM83_STOP reloc_8bit { | SM83_STOP reloc_8bit {
sect_ConstByte(0x10); sect_ConstByte(0x10);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(1);
} }
; ;
@@ -2419,9 +2501,11 @@ sm83_sub:
SM83_SUB op_a_n { SM83_SUB op_a_n {
sect_ConstByte(0xD6); sect_ConstByte(0xD6);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_SUB op_a_r { | SM83_SUB op_a_r {
sect_ConstByte(0x90 | $2); sect_ConstByte(0x90 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
@@ -2429,6 +2513,7 @@ sm83_swap:
SM83_SWAP reg_r { SM83_SWAP reg_r {
sect_ConstByte(0xCB); sect_ConstByte(0xCB);
sect_ConstByte(0x30 | $2); sect_ConstByte(0x30 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 4 : 2);
} }
; ;
@@ -2436,9 +2521,11 @@ sm83_xor:
SM83_XOR op_a_n { SM83_XOR op_a_n {
sect_ConstByte(0xEE); sect_ConstByte(0xEE);
sect_RelByte($2, 1); sect_RelByte($2, 1);
sym_IncrementCYCLESValue(2);
} }
| SM83_XOR op_a_r { | SM83_XOR op_a_r {
sect_ConstByte(0xA8 | $2); sect_ConstByte(0xA8 | $2);
sym_IncrementCYCLESValue($2 == REG_HL_IND ? 2 : 1);
} }
; ;
+2
View File
@@ -374,6 +374,7 @@ static Section *createSection(
sect.bank = bank; sect.bank = bank;
sect.align = alignment; sect.align = alignment;
sect.alignOfs = alignOffset; sect.alignOfs = alignOffset;
sect.cyclesCounter = 0;
out_RegisterNode(sect.src); out_RegisterNode(sect.src);
@@ -399,6 +400,7 @@ static Section *createSectionFragmentLiteral(Section const &parent) {
sect.bank = parent.bank == 0 ? UINT32_MAX : parent.bank; sect.bank = parent.bank == 0 ? UINT32_MAX : parent.bank;
sect.align = 0; sect.align = 0;
sect.alignOfs = 0; sect.alignOfs = 0;
sect.cyclesCounter = 0;
out_RegisterNode(sect.src); out_RegisterNode(sect.src);
+37
View File
@@ -44,6 +44,7 @@ static Symbol *SCOPESymbol;
static Symbol *globalScopeSymbol; static Symbol *globalScopeSymbol;
static Symbol *localScopeSymbol; static Symbol *localScopeSymbol;
static Symbol *RSSymbol; static Symbol *RSSymbol;
static Symbol *CYCLESSymbol;
static InternedStr PCName; static InternedStr PCName;
static InternedStr globalScopeName; static InternedStr globalScopeName;
@@ -108,6 +109,15 @@ static std::shared_ptr<std::string> localScopeCallback() {
return std::make_shared<std::string>(localScope->name.str()); return std::make_shared<std::string>(localScope->name.str());
} }
static int32_t CYCLESCallback() {
Section *section = sect_GetSymbolSection();
if (!section) {
error("`__CYCLES__` has no value outside of a section");
return 0;
}
return static_cast<int32_t>(section->cyclesCounter);
}
static int32_t PCCallback() { static int32_t PCCallback() {
return sect_GetSymbolSection()->org + sect_GetSymbolOffset(); return sect_GetSymbolSection()->org + sect_GetSymbolOffset();
} }
@@ -329,6 +339,10 @@ Symbol *sym_FindScopedValidSymbol(InternedStr symName) {
if (sym == SCOPESymbol && !sect_GetSymbolSection()) { if (sym == SCOPESymbol && !sect_GetSymbolSection()) {
return nullptr; return nullptr;
} }
// `__CYCLES__` has no value outside of a section
if (sym == CYCLESSymbol && !sect_GetSymbolSection()) {
return nullptr;
}
return sym; return sym;
} }
@@ -387,6 +401,15 @@ void sym_SetRSValue(int32_t value) {
RSSymbol->data = value; RSSymbol->data = value;
} }
void sym_IncrementCYCLESValue(uint32_t delta) {
// Calling this with no active section is an assembly error,
// but it will already have been reported
// by the instruction emission.
if (Section *section = sect_GetSymbolSection(); section) {
section->cyclesCounter += delta;
}
}
uint32_t Symbol::getConstantValue() const { uint32_t Symbol::getConstantValue() const {
if (isConstant()) { if (isConstant()) {
return getValue(); return getValue();
@@ -524,6 +547,15 @@ Symbol *sym_AddVar(InternedStr symName, int32_t value) {
} else if (sym->isDefined() && sym->type != SYM_VAR) { } else if (sym->isDefined() && sym->type != SYM_VAR) {
alreadyDefinedError(*sym, sym->type == SYM_LABEL ? "label" : "constant"); alreadyDefinedError(*sym, sym->type == SYM_LABEL ? "label" : "constant");
return sym; return sym;
} else if (sym == CYCLESSymbol) {
if (Section *section = sect_GetSymbolSection(); section) {
// This does not call `updateSymbolFilename` because `__CYCLES__` should stay as a
// built-in symbol, not registered for output in the object file.
section->cyclesCounter = static_cast<uint32_t>(value);
} else {
error("`__CYCLES__` has no value outside of a section");
}
return sym;
} else { } else {
updateSymbolFilename(*sym); updateSymbolFilename(*sym);
} }
@@ -729,6 +761,11 @@ void sym_Init(time_t now) {
RSSymbol = sym_AddVar(intern("_RS"), 0); RSSymbol = sym_AddVar(intern("_RS"), 0);
RSSymbol->isBuiltin = true; RSSymbol->isBuiltin = true;
CYCLESSymbol = &createSymbol(intern("__CYCLES__"));
CYCLESSymbol->type = SYM_VAR;
CYCLESSymbol->data = CYCLESCallback;
CYCLESSymbol->isBuiltin = true;
sym_AddString( sym_AddString(
intern("__RGBDS_VERSION__"), std::make_shared<std::string>(get_package_version_string()) intern("__RGBDS_VERSION__"), std::make_shared<std::string>(get_package_version_string())
) )
+63
View File
@@ -0,0 +1,63 @@
assert !def(__CYCLES__)
SECTION "test", ROM0
assert def(__CYCLES__)
assert __CYCLES__ == 0
nop
assert __CYCLES__ == 1
ld a, 42
assert __CYCLES__ == 3
dec a
assert __CYCLES__ == 4
db $c9
assert __CYCLES__ == 4 ; data does not increment __CYCLES__
PUSHS
assert !def(__CYCLES__)
SECTION FRAGMENT "fragmented", ROM0
assert def(__CYCLES__)
assert __CYCLES__ == 0
add [hl]
assert __CYCLES__ == 2
add b
assert __CYCLES__ == 3
DEF __CYCLES__ = 1
assert __CYCLES__ == 1
ccf
assert __CYCLES__ == 2
POPS
assert __CYCLES__ == 4
SECTION UNION "united", WRAM0
assert __CYCLES__ == 0
DEF __CYCLES__ = 42
assert __CYCLES__ == 42
SECTION FRAGMENT "fragmented", ROM0
assert __CYCLES__ == 2 ; this fragment continues from the previous one
SECTION UNION "united", WRAM0
assert __CYCLES__ == 42 ; this union continues from the previous one
SECTION "rom code", ROM0
assert __CYCLES__ == 0
ld hl, STARTOF("ram code")
assert __CYCLES__ == 3
LOAD "ram code", HRAM
assert __CYCLES__ == 0
ld hl, @
assert __CYCLES__ == 3
inc hl
assert __CYCLES__ == 5
ENDL
assert __CYCLES__ == 3
ENDSECTION
assert !def(__CYCLES)