#if not(ARCH_6502) #warn zp_reg module should be used only on 6502-compatible targets #endif noinline asm byte __mul_u8u8u8() { ? LDA #0 ? JMP __mul_u8u8u8_start __mul_u8u8u8_add: ? CLC ? ADC __reg __mul_u8u8u8_loop: ? ASL __reg __mul_u8u8u8_start: ? LSR __reg+1 ? BCS __mul_u8u8u8_add ? BNE __mul_u8u8u8_loop ? RTS } // divide __reg[0]/__reg[1] noinline asm byte __mod_u8u8u8u8() { ? LDA #0 ? LDX #7 ? CLC __divmod_u8u8u8u8_start: ? ROL __reg ? ROL ? CMP __reg+1 ? BCC __divmod_u8u8u8u8_skip ? SBC __reg+1 __divmod_u8u8u8u8_skip: ? DEX ? BPL __divmod_u8u8u8u8_start ? ROL __reg ? RTS } asm byte __div_u8u8u8u8() { ? JSR __mod_u8u8u8u8 ? LDA __reg ? RTS } #if ZPREG_SIZE >= 3 noinline asm word __mul_u16u8u16() { ? LDA #0 ? TAX ? JMP __mul_u16u8u16_start __mul_u16u8u16_add: ? CLC ? ADC __reg ? TAY ? TXA ? ADC __reg+1 ? TAX ? TYA __mul_u16u8u16_loop: ? ASL __reg ? ROL __reg+1 __mul_u16u8u16_start: ? LSR __reg+2 ? BCS __mul_u16u8u16_add ? BNE __mul_u16u8u16_loop ? RTS } // divide (__reg[1]:__reg[0])/__reg[2] // remainder in A, quotient in (__reg[1]:__reg[0]) noinline asm byte __mod_u16u8u16u8() { ? LDX #15 ? CLC // TODO: decide when #if OPTIMIZE_FOR_SPEED ? LDA __reg+2 ? BMI __divmod_u16u8u16u8_variant2 ? LDA #0 __divmod_u16u8u16u8_start: // for divisors <= 127 ? ROL __reg ? ROL __reg+1 ? ROL ? CMP __reg+2 ? BCC __divmod_u16u8u16u8_skip ? SBC __reg+2 __divmod_u16u8u16u8_skip: ? DEX ? BPL __divmod_u16u8u16u8_start ? ROL __reg ? ROL __reg+1 ? RTS #endif __divmod_u16u8u16u8_variant2: ? LDA #0 __divmod_u16u8u16u8_start2: // for divisors >= 128 ? ROL __reg ? ROL __reg+1 ? ROL ? BCS __divmod_u16u8u16u8_sub2 ? CMP __reg+2 ? BCC __divmod_u16u8u16u8_skip2 __divmod_u16u8u16u8_sub2: ? SBC __reg+2 ? SEC __divmod_u16u8u16u8_skip2: ? DEX ? BPL __divmod_u16u8u16u8_start2 ? ROL __reg ? ROL __reg+1 ? RTS } asm word __div_u16u8u16u8() { ? JSR __mod_u16u8u16u8 ? LDA __reg ? LDX __reg+1 ? RTS } #endif #if ZPREG_SIZE >= 4 noinline asm word call(word ax) { JMP ((__reg + 2)) } noinline asm word __mul_u16u16u16() { #if ZPREG_SIZE < 6 ? LDA __reg+1 ? PHA ? LDA __reg ? PHA ? TSX #else ? LDA __reg ? STA __reg+4 ? LDA __reg+1 ? STA __reg+5 #endif #if CPUFEATURE_65C02 && not(CPUFEATURE_65CE02) ? STZ __reg ? STZ __reg+1 #else ? LDA #0 ? STA __reg ? STA __reg+1 #endif ? LDY #16 __mul_u16u16u32_loop: ? ASL __reg ? ROL __reg+1 ? ROL __reg+2 ? ROL __reg+3 ? BCC __mul_u16u16u32_skip #if ZPREG_SIZE < 6 ? LDA $101,X #else ? LDA __reg+4 #endif ? CLC ? ADC __reg ? STA __reg #if ZPREG_SIZE < 6 ? LDA $102,X #else ? LDA __reg+5 #endif ? ADC __reg+1 ? STA __reg+1 ? BCC __mul_u16u16u32_skip ? INC __reg+2 __mul_u16u16u32_skip: ? DEY ? BNE __mul_u16u16u32_loop #if ZPREG_SIZE < 6 #if OPTIMIZE_FOR_SPEED ? INX ? INX ? TXS #else ? PLA ? PLA #endif #endif ? LDA __reg ? LDX __reg+1 ? RTS } // divide (__reg[1]:__reg[0])/(__reg[3]:__reg[2]) // remainder in (__reg[2]:__reg[3]), quotient in (__reg[1]:__reg[0]) noinline asm word __divmod_u16u16u16u16() { #if ZPREG_SIZE < 6 ? LDA __reg+3 ? PHA ? LDA __reg+2 ? PHA #else ? LDA __reg+2 ? STA __reg+4 ? LDA __reg+3 ? STA __reg+5 #endif #if CPUFEATURE_65C02 && not(CPUFEATURE_65CE02) ? STZ __reg+2 ? STZ __reg+3 #else ? LDA #0 ? STA __reg+2 ? STA __reg+3 #endif #if ZPREG_SIZE < 6 ? LDA #16 ? PHA ? TSX #else ? LDX #16 #endif __divmod_u16u16u16u16_loop: ? ASL __reg ? ROL __reg+1 ? ROL __reg+2 ? ROL __reg+3 ? LDA __reg+2 sec #if ZPREG_SIZE < 6 ? SBC $102,X #else ? SBC __reg+4 #endif ? TAY ? LDA __reg+3 #if ZPREG_SIZE < 6 ? SBC $103,X #else ? SBC __reg+5 #endif ? BCC __divmod_u16u16u16u16_skip ? STA __reg+3 ? STY __reg+2 ? INC __reg __divmod_u16u16u16u16_skip: #if ZPREG_SIZE < 6 ? DEC $101,X #else ? DEX #endif ? BNE __divmod_u16u16u16u16_loop #if ZPREG_SIZE < 6 #if OPTIMIZE_FOR_SIZE ? PLA ? PLA ? PLA #else ? INX ? INX ? INX ? TXS #endif #endif ? RTS } asm word __div_u16u16u16u16() { JSR __divmod_u16u16u16u16 ? LDA __reg ? LDX __reg+1 ? RTS } asm word __mod_u16u16u16u16() { JSR __divmod_u16u16u16u16 ? LDA __reg+2 ? LDX __reg+3 ? RTS } #endif