mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-27 04:29:34 +00:00
358 lines
6.3 KiB
Plaintext
358 lines
6.3 KiB
Plaintext
|
|
#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
|