1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-03 10:29:58 +00:00
millfork/include/i80_math.mfk

333 lines
6.0 KiB
Plaintext
Raw Normal View History

2018-09-28 21:45:26 +00:00
#if not(ARCH_I80)
#warn i80_math module should be used only on 8080-like targets
#endif
#pragma zilog_syntax
2019-09-30 22:46:15 +00:00
#if CPUFEATURE_Z80_NEXT
inline asm byte __mul_u8u8u8() {
? LD E,A
? MUL
? LD A, E
? RET
}
#elseif CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY
//A = A * D
2018-12-19 00:09:27 +00:00
noinline asm byte __mul_u8u8u8() {
2018-09-28 21:45:26 +00:00
? 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
2018-12-19 00:09:27 +00:00
noinline asm byte __mul_u8u8u8() {
2018-09-28 21:45:26 +00:00
? 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
2018-12-14 21:50:20 +00:00
2019-06-05 23:17:34 +00:00
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
}
2019-09-04 19:17:06 +00:00
noinline asm word __mul_u16u8u16() {
2018-12-14 21:50:20 +00:00
? 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
}
2019-09-04 19:17:06 +00:00
#if CPUFEATURE_Z80 || CPUFEATURE_GAMEBOY
noinline asm word __mul_u16u16u16() {
2019-09-15 17:47:19 +00:00
LD HL,0
LD A,16
2019-09-04 19:17:06 +00:00
__mul_u16u16u16_loop:
2019-09-15 17:47:19 +00:00
ADD HL,HL
RL E
RL D
JR NC,__mul_u16u16u16_skip
ADD HL,BC
2019-09-04 19:17:06 +00:00
__mul_u16u16u16_skip:
2019-09-15 17:47:19 +00:00
DEC A
JR NZ,__mul_u16u16u16_loop
RET
2019-09-04 19:17:06 +00:00
}
#else
noinline asm word __mul_u16u16u16() {
ld hl,0
2019-09-15 17:47:19 +00:00
CALL __mul_u16u16u16_q
CALL __mul_u16u16u16_q
CALL __mul_u16u16u16_q
JP __mul_u16u16u16_q
2019-09-04 19:17:06 +00:00
}
noinline asm word __mul_u16u16u16_q(word hl) {
2019-09-15 17:47:19 +00:00
CALL __mul_u16u16u16_s
CALL __mul_u16u16u16_s
CALL __mul_u16u16u16_s
JP __mul_u16u16u16_s
2019-09-04 19:17:06 +00:00
}
noinline asm word __mul_u16u16u16_s(word hl) {
2019-09-15 17:47:19 +00:00
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
2019-09-04 19:17:06 +00:00
}
2019-09-15 17:47:19 +00:00
#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