Implement 32bit divmod based on Bisqwit's algorithm, implement 16 and 32-bit decimal print
This commit is contained in:
parent
c7af8e833b
commit
b613ab8965
4 changed files with 268 additions and 44 deletions
50
c64/main.asm
50
c64/main.asm
|
@ -2,12 +2,29 @@
|
|||
|
||||
#import "math.inc"
|
||||
|
||||
* = $0801 // BASIC start address (#2049)
|
||||
.byte $0d,$08,$dc,$07,$9e,$20,$34,$39 // BASIC loader to start at $c000...
|
||||
.byte $31,$35,$32,$00,$00,$00 // puts BASIC line 2012 SYS 49152
|
||||
BasicUpstart2(main)
|
||||
|
||||
.align $100
|
||||
* = * "Square table"
|
||||
square1_lo:
|
||||
.fill 512, 0
|
||||
square1_hi:
|
||||
.fill 512, 0
|
||||
square2_lo:
|
||||
.fill 512, 0
|
||||
square2_hi:
|
||||
.fill 512, 0
|
||||
|
||||
* = * "Day 1 input"
|
||||
day01_input:
|
||||
.import text "../rust/inputs/day01"
|
||||
.byte 0
|
||||
|
||||
//* = $8000 "Cartridge ROM"
|
||||
|
||||
//* = $a000 "Basic ROM"
|
||||
|
||||
* = $c000
|
||||
|
||||
.const SCREEN_RAM = $0400
|
||||
.const COLOR_RAM = $d800
|
||||
|
||||
|
@ -32,20 +49,33 @@
|
|||
main:
|
||||
jsr clear_screen
|
||||
|
||||
// lda #0
|
||||
// sta $d020
|
||||
// sta $d021
|
||||
// Swap out BASIC and kernal
|
||||
sei
|
||||
lda %00110000
|
||||
sta $01
|
||||
|
||||
jsr day01
|
||||
jsr generate_multiplication_tables
|
||||
|
||||
// Test division by 10
|
||||
lda #$cc
|
||||
sta udivmod32_dividend + 0
|
||||
lda #$28
|
||||
sta udivmod32_dividend + 1
|
||||
lda #$f9
|
||||
sta udivmod32_dividend + 2
|
||||
lda #$07
|
||||
sta udivmod32_dividend + 3
|
||||
|
||||
jsr print_decimal_u32
|
||||
|
||||
!loop:
|
||||
// inc $d020
|
||||
jmp !loop-
|
||||
|
||||
|
||||
buffer:
|
||||
.fill $0100, 0
|
||||
.fill $0400, 0
|
||||
|
||||
|
||||
#import "day01.asm"
|
||||
#import "screen.asm"
|
||||
#import "math.asm"
|
||||
|
|
89
c64/math.asm
89
c64/math.asm
|
@ -1,3 +1,5 @@
|
|||
// vim: filetype=kickass
|
||||
|
||||
.const T1=$03
|
||||
.const T2=$fd
|
||||
.const PRODUCT=$22
|
||||
|
@ -282,18 +284,32 @@ generate_multiplication_tables:
|
|||
//
|
||||
// udivmod32
|
||||
//
|
||||
// TODO consistent name
|
||||
// TODO document input, output, destroyed
|
||||
// 32-bit unsigned integer div/mod routine.
|
||||
// Based on https://bisqwit.iki.fi/story/howto/bitmath/
|
||||
//
|
||||
// TODO consistent name
|
||||
// TODO could probably be optimized further
|
||||
//
|
||||
// Input:
|
||||
// - udivmod32_dividend: LSB of the dividend.
|
||||
// - udivmod32_divisor: LSB of the divisor.
|
||||
//
|
||||
// Output:
|
||||
// - udivmod32_result: LSB of the division result.
|
||||
// - udivmod32_remainder: LSB of the modulo result.
|
||||
//
|
||||
// Destroys: a, $20..$2b
|
||||
//
|
||||
.const udivmod32_dividend = $10 // 11,12,13
|
||||
.const udivmod32_divisor = $14 // 15,16,17
|
||||
.const udivmod32_result = $18 // 19,1a,1b
|
||||
.const udivmod32_remainder = $1c // 1d,1e,1f
|
||||
|
||||
.const scaled_divisor = $20 // ..23
|
||||
.const multiple = $28 // ..2b
|
||||
.const temp = $2b // ..2f
|
||||
.const multiple = $24 // ..27
|
||||
.const temp = $28 // ..2b
|
||||
udivmod32:
|
||||
lda #0
|
||||
sta udivmod32_result + 0
|
||||
sta udivmod32_result + 1
|
||||
sta udivmod32_result + 2
|
||||
sta udivmod32_result + 3
|
||||
|
||||
// if (divisor == 0) {
|
||||
lda udivmod32_divisor + 0
|
||||
bne !if_end+
|
||||
|
@ -322,12 +338,12 @@ udivmod32:
|
|||
// remainder = dividend;
|
||||
lda udivmod32_dividend + 0
|
||||
sta udivmod32_remainder + 0
|
||||
lda udivmod32_dividend + 0
|
||||
sta udivmod32_remainder + 0
|
||||
lda udivmod32_dividend + 0
|
||||
sta udivmod32_remainder + 0
|
||||
lda udivmod32_dividend + 0
|
||||
sta udivmod32_remainder + 0
|
||||
lda udivmod32_dividend + 1
|
||||
sta udivmod32_remainder + 1
|
||||
lda udivmod32_dividend + 2
|
||||
sta udivmod32_remainder + 2
|
||||
lda udivmod32_dividend + 3
|
||||
sta udivmod32_remainder + 3
|
||||
|
||||
|
||||
// uint32_t multiple = 1;
|
||||
|
@ -338,25 +354,12 @@ udivmod32:
|
|||
sta multiple + 2
|
||||
sta multiple + 3
|
||||
|
||||
// uint32_t result = 0;
|
||||
sta udivmod32_result + 0
|
||||
sta udivmod32_result + 1
|
||||
sta udivmod32_result + 2
|
||||
sta udivmod32_result + 3
|
||||
|
||||
|
||||
// while (scaled_divisor < dividend) {
|
||||
// while (!(scaled_divisor & 0x80000000)) {
|
||||
!while_start:
|
||||
sec
|
||||
lda scaled_divisor + 0
|
||||
sbc udivmod32_dividend + 0
|
||||
lda scaled_divisor + 1
|
||||
sbc udivmod32_dividend + 1
|
||||
lda scaled_divisor + 2
|
||||
sbc udivmod32_dividend + 2
|
||||
lda scaled_divisor + 3
|
||||
sbc udivmod32_dividend + 3
|
||||
bcs !while_end+
|
||||
lda #$80
|
||||
and scaled_divisor + 3
|
||||
bne !while_end+
|
||||
|
||||
// scaled_divisor <<= 1
|
||||
asl scaled_divisor + 0
|
||||
|
@ -382,15 +385,19 @@ udivmod32:
|
|||
lda udivmod32_remainder + 0
|
||||
sbc scaled_divisor + 0
|
||||
sta temp + 0
|
||||
|
||||
lda udivmod32_remainder + 1
|
||||
sbc scaled_divisor + 1
|
||||
sta temp + 1
|
||||
|
||||
lda udivmod32_remainder + 2
|
||||
sbc scaled_divisor + 2
|
||||
sta temp + 2
|
||||
|
||||
lda udivmod32_remainder + 3
|
||||
sbc scaled_divisor + 3
|
||||
sta temp + 3
|
||||
|
||||
bcc !if_end+
|
||||
|
||||
// remain -= scaled_divisor;
|
||||
|
@ -403,6 +410,24 @@ udivmod32:
|
|||
lda temp + 3
|
||||
sta udivmod32_remainder + 3
|
||||
|
||||
// result += multiple;
|
||||
clc
|
||||
lda udivmod32_result + 0
|
||||
adc multiple + 0
|
||||
sta udivmod32_result + 0
|
||||
|
||||
lda udivmod32_result + 1
|
||||
adc multiple + 1
|
||||
sta udivmod32_result + 1
|
||||
|
||||
lda udivmod32_result + 2
|
||||
adc multiple + 2
|
||||
sta udivmod32_result + 2
|
||||
|
||||
lda udivmod32_result + 3
|
||||
adc multiple + 3
|
||||
sta udivmod32_result + 3
|
||||
|
||||
// }
|
||||
!if_end:
|
||||
|
||||
|
|
45
c64/math.inc
45
c64/math.inc
|
@ -1,4 +1,8 @@
|
|||
// vim: filetype=kickass
|
||||
.const udivmod32_dividend = $10 // 11,12,13
|
||||
.const udivmod32_divisor = $14 // 15,16,17
|
||||
.const udivmod32_result = $18 // 19,1a,1b
|
||||
.const udivmod32_remainder = $1c // 1d,1e,1f
|
||||
|
||||
.macro i8_div5_a() {
|
||||
sta zp_temp
|
||||
|
@ -95,6 +99,47 @@
|
|||
i16_i16_add(lo, hi, $fd, $fe)
|
||||
}
|
||||
|
||||
.macro u32_mul2(lsb) {
|
||||
asl lsb + 0
|
||||
rol lsb + 1
|
||||
rol lsb + 2
|
||||
rol lsb + 3
|
||||
}
|
||||
|
||||
.macro u32_mul10(lsb) {
|
||||
u32_mul2(lsb)
|
||||
|
||||
lda lsb + 0
|
||||
sta $2c + 0
|
||||
lda lsb + 1
|
||||
sta $2c + 1
|
||||
lda lsb + 2
|
||||
sta $2c + 2
|
||||
lda lsb + 3
|
||||
sta $2c + 3
|
||||
|
||||
u32_mul2(lsb)
|
||||
u32_mul2(lsb)
|
||||
|
||||
i32_i32_add(lsb, $2c)
|
||||
}
|
||||
|
||||
.macro i32_i32_add(dst, src) {
|
||||
clc
|
||||
lda dst + 0
|
||||
adc src + 0
|
||||
sta dst + 0
|
||||
lda dst + 1
|
||||
adc src + 1
|
||||
sta dst + 1
|
||||
lda dst + 2
|
||||
adc src + 2
|
||||
sta dst + 2
|
||||
lda dst + 3
|
||||
adc src + 3
|
||||
sta dst + 3
|
||||
}
|
||||
|
||||
// Destroys: a, dst_lo, dst_hi
|
||||
.macro i16_i8_add_a(dst_lo, dst_hi) {
|
||||
clc
|
||||
|
|
128
c64/screen.asm
128
c64/screen.asm
|
@ -52,9 +52,7 @@ print_newline:
|
|||
sta cursor_pointer_lo
|
||||
bcc !done+
|
||||
inc cursor_pointer_hi
|
||||
|
||||
!done:
|
||||
rts
|
||||
|
||||
|
||||
//
|
||||
|
@ -136,6 +134,13 @@ write_string:
|
|||
rts
|
||||
|
||||
|
||||
.macro i16_print_hex_0x(lo, hi) {
|
||||
lda hi
|
||||
jsr print_hex_0x
|
||||
lda lo
|
||||
jsr print_hex
|
||||
}
|
||||
|
||||
print_hex_0x:
|
||||
sta zp_temp
|
||||
|
||||
|
@ -180,3 +185,122 @@ print_hex:
|
|||
!hex_chars:
|
||||
.text "0123456789ABCDEF"
|
||||
|
||||
|
||||
print_decimal_u16:
|
||||
ldy #6
|
||||
|
||||
// Null-terminate the buffer
|
||||
lda #0
|
||||
sta !buffer+, y
|
||||
|
||||
!loop:
|
||||
u16_div10()
|
||||
|
||||
lda $24
|
||||
sta $22
|
||||
|
||||
lda $25
|
||||
sta $23
|
||||
|
||||
i16_mul10($22, $23)
|
||||
|
||||
i16_i16_sub($22, $23, $03, $04, $22, $23)
|
||||
|
||||
lda $24
|
||||
sta $03
|
||||
lda $25
|
||||
sta $04
|
||||
|
||||
lda $22
|
||||
clc
|
||||
adc #'0'
|
||||
|
||||
sta !buffer+ - 1, y
|
||||
|
||||
dey
|
||||
bne !loop-
|
||||
|
||||
// Find the first digit
|
||||
ldy #0
|
||||
|
||||
!:
|
||||
lda !buffer+, y
|
||||
iny
|
||||
cmp #'0'
|
||||
beq !-
|
||||
dey
|
||||
tya
|
||||
|
||||
clc
|
||||
adc #<(!buffer+)
|
||||
sta $03
|
||||
lda #0
|
||||
adc #>(!buffer+)
|
||||
sta $04
|
||||
jsr write_string
|
||||
|
||||
rts
|
||||
|
||||
|
||||
//
|
||||
// Input:
|
||||
// - udivmod32_dividend - Number to print
|
||||
print_decimal_u32:
|
||||
ldy #11
|
||||
|
||||
// Null-terminate the buffer
|
||||
lda #0
|
||||
sta !buffer+, y
|
||||
|
||||
lda #0
|
||||
sta udivmod32_divisor + 3
|
||||
sta udivmod32_divisor + 2
|
||||
sta udivmod32_divisor + 1
|
||||
lda #10
|
||||
sta udivmod32_divisor + 0
|
||||
|
||||
!loop:
|
||||
jsr udivmod32
|
||||
|
||||
lda udivmod32_remainder
|
||||
clc
|
||||
adc #'0'
|
||||
|
||||
sta !buffer+ - 1, y
|
||||
|
||||
lda udivmod32_result + 0
|
||||
sta udivmod32_dividend + 0
|
||||
lda udivmod32_result + 1
|
||||
sta udivmod32_dividend + 1
|
||||
lda udivmod32_result + 2
|
||||
sta udivmod32_dividend + 2
|
||||
lda udivmod32_result + 3
|
||||
sta udivmod32_dividend + 3
|
||||
|
||||
dey
|
||||
bne !loop-
|
||||
|
||||
// Find the first digit
|
||||
ldy #0
|
||||
|
||||
!:
|
||||
lda !buffer+, y
|
||||
iny
|
||||
cmp #'0'
|
||||
beq !-
|
||||
dey
|
||||
tya
|
||||
|
||||
clc
|
||||
adc #<(!buffer+)
|
||||
sta $03
|
||||
lda #0
|
||||
adc #>(!buffer+)
|
||||
sta $04
|
||||
jsr write_string
|
||||
|
||||
rts
|
||||
|
||||
|
||||
!buffer:
|
||||
.fill 12, 0
|
||||
|
|
Loading…
Reference in a new issue