#if not(ARCH_I80) #warn i80_math module should be used only on 8080-like targets #endif #pragma zilog_syntax #if CPUFEATURE_Z80_NEXT inline asm byte __mul_u8u8u8() { ? LD E,A ? MUL ? LD A, E ? RET } #elseif CPUFEATURE_R800 inline asm byte __mul_u8u8u8() { ? MULUB A,D ? LD A,L ? RET } #elseif CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY //A = A * D noinline asm byte __mul_u8u8u8() { ? LD E,A ? LD A, 0 ? JR __mul_u8u8u8_start __mul_u8u8u8_add: ? ADD A,E __mul_u8u8u8_loop: ? SLA E __mul_u8u8u8_start: ? SRL D ? JR C, __mul_u8u8u8_add ? JR NZ, __mul_u8u8u8_loop ? RET } #else noinline asm byte __mul_u8u8u8() { ? LD E,A ? LD C, 0 ? JP __mul_u8u8u8_start __mul_u8u8u8_add: ? LD A,C ? ADD A,E ? LD C,A __mul_u8u8u8_loop: ? LD A,E ? ADD A,A ? LD E,A __mul_u8u8u8_start: ? OR A ? LD A,D ? RRA ? LD D,A ? JP C, __mul_u8u8u8_add ? OR A ? JP NZ, __mul_u8u8u8_loop ? LD A,C ? RET } #endif noinline asm void __divmod_u16u8u16u8() { ? XOR A ? LD B, 16 __divmod_u16u8u16u8_loop: ? ADD HL,HL ? RLA #if CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY ? JR C, __divmod_u16u8u16u8_overflow #else ? JP C, __divmod_u16u8u16u8_overflow #endif ? CP D #if CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY ? JR C, __divmod_u16u8u16u8_skip #else ? JP C, __divmod_u16u8u16u8_skip #endif __divmod_u16u8u16u8_overflow: ? SUB D ? INC L __divmod_u16u8u16u8_skip: #if CPUFEATURE_Z80 ? DJNZ __divmod_u16u8u16u8_loop #elseif CPUFEATURE_GAMEBOY ? DEC B ? JR NZ, __divmod_u16u8u16u8_loop #else ? DEC B ? JP NZ, __divmod_u16u8u16u8_loop #endif ? RET } #if CPUFEATURE_R800 inline asm word __mul_u16u8u16() { ? LD L,A ? LD H,0 ? MULUW HL,DE ? RET } #else // HL=A*DE noinline asm word __mul_u16u8u16() { ? LD HL,0 ? LD B,8 __mul_u16u8u16_loop: ? ADD HL,HL ? ADC A,A #if CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY ? JR NC,__mul_u16u8u16_skip #else ? JP NC,__mul_u16u8u16_skip #endif ? ADD HL,DE __mul_u16u8u16_skip: #if CPUFEATURE_Z80 ? DJNZ __mul_u16u8u16_loop #elseif CPUFEATURE_GAMEBOY ? DEC B ? JR NZ,__mul_u16u8u16_loop #else ? DEC B ? JP NZ,__mul_u16u8u16_loop #endif ? RET } #endif #if CPUFEATURE_R800 inline asm word __mul_u16u16u16() { ? EX DE,HL ? MULUW HL,BC ? RET } #elseif CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY // HL=BC*DE noinline asm word __mul_u16u16u16() { LD HL,0 LD A,16 __mul_u16u16u16_loop: ADD HL,HL RL E RL D JR NC,__mul_u16u16u16_skip ADD HL,BC __mul_u16u16u16_skip: DEC A JR NZ,__mul_u16u16u16_loop RET } #else noinline asm word __mul_u16u16u16() { ld hl,0 CALL __mul_u16u16u16_q CALL __mul_u16u16u16_q CALL __mul_u16u16u16_q JP __mul_u16u16u16_q } noinline asm word __mul_u16u16u16_q(word hl) { CALL __mul_u16u16u16_s CALL __mul_u16u16u16_s CALL __mul_u16u16u16_s JP __mul_u16u16u16_s } noinline asm word __mul_u16u16u16_s(word hl) { ADD HL,HL LD A,E ADD A,E LD E,A LD A,D ADC A,D LD D,A RET NC ADD HL,BC RET } #endif #if CPUFEATURE_Z80 // HL/DE = DE rem HL noinline asm word __divmod_u16u16u16u16() { LD A,H LD C,L LD HL,0 LD B,16 __divmod_u16u16u16u16_loop: #if CPUFEATURE_Z80_ILLEGALS SLL C #else SCF RL C #endif RLA ADC HL,HL SBC HL,DE JR NC,__divmod_u16u16u16u16_skip ADD HL,DE DEC C __divmod_u16u16u16u16_skip: DJNZ __divmod_u16u16u16u16_loop LD D,A LD E,C RET } #elseif CPUFEATURE_8080 // HL/DE = DE rem HL // ABI could be changed, but the optimizer relies on it asm word __divmod_u16u16u16u16() { ? LD B,D ? LD C,E ? LD DE,0 #if OPTIMIZE_FOR_SPEED ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u #else ? CALL __divmod_u16u16u16u16_q ? CALL __divmod_u16u16u16u16_q ? CALL __divmod_u16u16u16u16_q ? CALL __divmod_u16u16u16u16_q #endif ? EX DE,HL ? RET } #if not(OPTIMIZE_FOR_SPEED) asm void __divmod_u16u16u16u16_q(){ ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? JP __divmod_u16u16u16u16_u } #endif noinline asm void __divmod_u16u16u16u16_u(){ ADD HL,HL INC L LD A,E RLA LD E,A LD A,D RLA LD D,A LD A,E SUB C LD E,A LD A,D SBC A,B LD D,A RET NC EX DE,HL ADD HL, BC EX DE,HL DEC L RET } #elseif CPUFEATURE_GAMEBOY // HL/DE = DE rem HL // ABI could be changed, but the optimizer relies on it asm word __divmod_u16u16u16u16() { ? LD B,D ? LD C,E ? LD D,H ? LD E,L ? LD HL,0 #if OPTIMIZE_FOR_SPEED ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? JP __divmod_u16u16u16u16_u #else ? CALL __divmod_u16u16u16u16_q ? CALL __divmod_u16u16u16u16_q ? CALL __divmod_u16u16u16u16_q ? JP __divmod_u16u16u16u16_q #endif } #if not(OPTIMIZE_FOR_SPEED) asm void __divmod_u16u16u16u16_q(){ ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? CALL __divmod_u16u16u16u16_u ? JP __divmod_u16u16u16u16_u } #endif noinline asm void __divmod_u16u16u16u16_u() { SCF RL E RL D RL L RL H LD A,L SUB C LD L,A LD A,H SBC A,B LD H,A RET NC ADD HL,BC DEC E RET } #else #warn No implementation of 16-bit division for this target #endif