English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 25 June 2021, 10:39   #341
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,043
And down to 600 bytes, also there was a compile error (wrong operand order with a cmp).
Changes are marked with a comment (about a dozen), shouldn't be too hard to find. I also renamed a couple of things for clarity.
maxn is 9304 digits, btw.

Code:
OldOpenLibrary = -408
CloseLibrary = -414
Output = -60
Input = -54
Write = -48
Read = -42
Forbid = -132
Permit = -138
AddIntServer = -168
RemIntServer = -174
VBlankFrequency = 530
INTB_VERTB = 5     ;for vblank interrupt
NT_INTERRUPT = 2   ;node type

;N = 7*D/2 ;D digits, e.g., N = 350 for 100 digits

start
         lea libname(pc),a1         ;open the dos library
         move.l 4.W,a5
         move.l a5,a6
         jsr OldOpenLibrary(a6)
         move.l d0,a6
         jsr Output(a6)          ;get stdout
         lea time(PC),A4
;         lea rasteri(PC),A0
;         move.l A0,-(SP)      ; is_Code
         lea rasteri(PC),A2
         move.l A2,-(SP)      ; is_Code
         move.l A4,-(SP)      ; is_Data
         clr.l -(SP)          ; ln_Name
         move.w #NT_INTERRUPT<<8+0,-(SP)	; ln_Type, ln_Pri
         subq.l #2*4,SP				; ln_Succ, ln_Pred
         move.l d0,-(A4)            ;cout
;         move.w	#((65536-(ra-start))/(7<<2))<<2,D7	; d7.w=maxn
         move.w	#((65536-(workspace-start))/(7<<2))<<2,D7	; d7.w=maxn
         moveq #10,D4
	subq.l	#rasteri-writetext,a2		; a2=writetext
         moveq #msg1-cout,D2 ; must be checked if in moveq range, the longest text can be moved at end
         moveq #msg4-msg1,d3
;         bsr .write
	jsr	(a2)		; writetext

         bsr.w getnum		; returns value in d1 and d5
         addq.w #3,d5
         and.w #$fffc,d5
         move.w d5,d6
;invalid         cmp.b D4,(a0)    ; 10
         cmp.b (a0),d4    ; 10
         bne.b .l21
         cmp.w d1,d5
         beq.b .l7
.l21
         bsr.w PR0000
         moveq #msg3-cout,D2
         moveq #msg2-msg3,d3
;         bsr .write
	jsr	(a2)		; writetext

.l7 
         mulu.w #7,d6          ;kv = d6
         lsr.l #2,D6               ; /4
         move.l d6,d7
;         lea ra(pc),a3
         lea workspace(pc),a3

         exg a5,a6
         jsr Forbid(a6)
         moveq #INTB_VERTB,d0
         move.l SP,A1
         jsr AddIntServer(a6)
         exg a5,a6
 
         move.l #2000*65537,d0
         move.l a3,a0
.fill    move.l d0,(a0)+
         subq.l #1,D7
         bne.b .fill

         move.l D7,-(SP)    ; cv
         lea 10000.W,A2

.l0      moveq #0,D5       ;d <- 0
         move.l d6,d4     ;i <- kv, i <- i*2
         lsl.l #2,D4           ; *4
         adda.l d4,a3
         subq.l #1,d4     ;b <- 2*i-1
         move.l A2,D1
         bra.b .l4

.longdiv
         swap d0
         move.w d0,d7
         divu.w d4,d7
         swap d7
         move.w d7,d0
         swap d0
         divu.w d4,d0

         move.w d0,d7
         exg d0,d7
         clr.w d7
         swap d7
         move.w d7,(a3)     ;r[i] <- d%b
         bra.b .enddiv

.l2
         sub.l d0,d5
         sub.l d7,d5
         lsr.l #1,d5
.l4
         move.w -(a3),d0      ; r[i]
         mulu.w d1,d0       ;r[i]*10000
         add.l d0,d5       ;d += r[i]*10000
         move.l d5,d0
         divu.w d4,d0
         bvs.s .longdiv

         move.w d0,d7
         clr.w d0
         swap d0
         move.w d0,(a3)     ;r[i] <- d%b
.enddiv
         subq.l #2,d4    ;i <- i - 1
         bcc.b .l2       ;the main loop
         divu.w d1,d5
 
         add.w (SP),D5 ; cv
         move.l D5,(SP) ; cv
         bsr.b PR0000
         subq.l #7,d6   ;kv
         bne.b .l0
         addq.l #4,SP ;  restore stack

         exg a5,a6
         moveq #INTB_VERTB,d0
         move.l SP,A1
         jsr RemIntServer(a6)
         jsr Permit(a6)
        exg a5,a6
        lea     22(SP),SP                ; restore stack (is_Size)
 
        movem.l (A4),D1/D5        ; last use of cout and time
	move.l	a4,d2			; buffer

	move.b	VBlankFrequency(a5),d6	; d6.l is 0
	move.l	d6,d0
	add.w	d0,d0
	divu.w	d0,d5			; d5 = seconds
	move.l	d5,d4
	swap	d4
	mulu.w	#100,d4
	add.l	d4,d6			; round up (+0.5)
	divu.w	d0,d6			; d6 = 1/100ths
        moveq   #10,D0

	move.b	#' ',(a4)+

	moveq	#0,d4			; skip leading zeroes
        move.l  A2,D7	                ; 10000
	bsr.b	SPrintTime

	move.b	#'.',(a4)+

	moveq	#'0',d4			; print leading zeroes
	move.w	d6,d5
	moveq	#10,d7
	bsr.b	SPrintTime

	move.b	d0,(a4)+		; newline

	move.l	a4,d3
	sub.l	d2,d3
	jsr	Write(a6)

	move.l	a6,a1
	move.l	a5,a6
	jmp	CloseLibrary(a6)	; END OF PROGRAM

SPrintTime	; d5=value, a4=buffer
.Next	ext.l	d5
	divu.w	d7,d5
	cmp.b	d4,d5
	beq.b	.LeadZero
	moveq	#'0',d4
	add.b	d4,d5
	move.b	d5,(a4)+
.LeadZero
	swap	d5
	divu.w	d0,d7
	bne.b	.Next
	rts

PR0000     ;prints d5, uses a0,a1(scratch),d0,d1,d2,d3
      moveq #4,D3
      moveq #buf-cout,D2
        move.w	#$0100,a0
	move.l	#$2f3a2f2f,d0
	move.w	#1000,d1
.b1000	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b1000
	add.w	d1,d5

	moveq	#100,d1
.b100	addq.b	#1,d0
	sub.w	d1,d5
	bcc.b	.b100
	add.w	d1,d5

	swap	d0
	moveq	#10,d1
.b10	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b10
	add.b	d5,d0

        move.l D0,buf-cout(A4) ; buf
writetext
        move.l (A4),D1    ; cout
        add.l  A4,D2 ; buf
        jmp Write(A6) ;call Write(stdout,buff,size)

; If interrupt priority is >= 10 then a0 must point at $dff000 on exit
rasteri
      addq.l #2,(a1)
      moveq #0,d0  ; must set Z flag on exit!
      rts

	cnop 0,4
cout dc.l 0
time dc.l 0
buf ds.b 4

; Overwritten code/data start here. 
workspace

msg1  dc.b 'number pi calculator v13',10
msg4 dc.b 'number of digits (up to '
msg5 dc.b ')? '
msg3 dc.b ' digits will be printed',10
msg2
      even

getnum
.error   moveq #msg4-cout,D2
         moveq #msg5-msg4,d3
;         bsr.b .write
	jsr	(a2)		; writetext
         move.w d7,d5
         bsr.w PR0000
         moveq #msg5-cout,D2
         moveq #msg3-msg5,d3
;         bsr.b .write
	jsr	(a2)		; writetext
        jsr Input(a6)          ;get stdin
        move.l d0,d1
        moveq #msg1-cout,D2
        add.l A4,D2
        moveq #4+1,d3     ;+ newline
        jsr Read(a6)
 
        move.l	d2,a0
	moveq	#0,d5
.loop	subq.w	#1,d0
	beq.b	.done
	move.w	#256-'0',d6
	add.b	(a0)+,d6
;	cmp.w	#9,d6
;	bhi.b	.error
	cmp.w	d4,d6		; digit >= 10?
	bhs.b	.error
	mulu.w	d4,d5		; *10
	add.w	d6,d5
	bra.b	.loop
.done
	cmp.w d7,d5
	bhi.b .error
	move.w d5,d1
	beq.b .error
	rts

libname  dc.b "dos.library",0

Buffy
     ds.b 65536-(Buffy-start)

; asm-one&co
;	PRINTV	Buffy-start+36		; 36 = hunk overhead
;	PRINTV	((65536-(workspace-start))/(7<<2))<<2
a/b is offline  
Old 25 June 2021, 11:18   #342
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,423
Just for reference: what was the original size & speed of the program?
I'm loving all the optimisations I'm seeing and I'd like to put them in perspective after all the work that has gone into it
roondar is offline  
Old 25 June 2021, 11:30   #343
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Quote:
Originally Posted by a/b View Post
And down to 600 bytes, also there was a compile error (wrong operand order with a cmp).
Changes are marked with a comment (about a dozen), shouldn't be too hard to find. I also renamed a couple of things for clarity.
maxn is 9304 digits, btw.

Code:
OldOpenLibrary = -408
CloseLibrary = -414
Output = -60
Input = -54
Write = -48
Read = -42
Forbid = -132
Permit = -138
AddIntServer = -168
RemIntServer = -174
VBlankFrequency = 530
INTB_VERTB = 5     ;for vblank interrupt
NT_INTERRUPT = 2   ;node type

;N = 7*D/2 ;D digits, e.g., N = 350 for 100 digits

start
         lea libname(pc),a1         ;open the dos library
         move.l 4.W,a5
         move.l a5,a6
         jsr OldOpenLibrary(a6)
         move.l d0,a6
         jsr Output(a6)          ;get stdout
         lea time(PC),A4
;         lea rasteri(PC),A0
;         move.l A0,-(SP)      ; is_Code
         lea rasteri(PC),A2
         move.l A2,-(SP)      ; is_Code
         move.l A4,-(SP)      ; is_Data
         clr.l -(SP)          ; ln_Name
         move.w #NT_INTERRUPT<<8+0,-(SP)	; ln_Type, ln_Pri
         subq.l #2*4,SP				; ln_Succ, ln_Pred
         move.l d0,-(A4)            ;cout
;         move.w	#((65536-(ra-start))/(7<<2))<<2,D7	; d7.w=maxn
         move.w	#((65536-(workspace-start))/(7<<2))<<2,D7	; d7.w=maxn
         moveq #10,D4
	subq.l	#rasteri-writetext,a2		; a2=writetext
         moveq #msg1-cout,D2 ; must be checked if in moveq range, the longest text can be moved at end
         moveq #msg4-msg1,d3
;         bsr .write
	jsr	(a2)		; writetext

         bsr.w getnum		; returns value in d1 and d5
         addq.w #3,d5
         and.w #$fffc,d5
         move.w d5,d6
;invalid         cmp.b D4,(a0)    ; 10
         cmp.b (a0),d4    ; 10
         bne.b .l21
         cmp.w d1,d5
         beq.b .l7
.l21
         bsr.w PR0000
         moveq #msg3-cout,D2
         moveq #msg2-msg3,d3
;         bsr .write
	jsr	(a2)		; writetext

.l7 
         mulu.w #7,d6          ;kv = d6
         lsr.l #2,D6               ; /4
         move.l d6,d7
;         lea ra(pc),a3
         lea workspace(pc),a3

         exg a5,a6
         jsr Forbid(a6)
         moveq #INTB_VERTB,d0
         move.l SP,A1
         jsr AddIntServer(a6)
         exg a5,a6
 
         move.l #2000*65537,d0
         move.l a3,a0
.fill    move.l d0,(a0)+
         subq.l #1,D7
         bne.b .fill

         move.l D7,-(SP)    ; cv
         lea 10000.W,A2

.l0      moveq #0,D5       ;d <- 0
         move.l d6,d4     ;i <- kv, i <- i*2
         lsl.l #2,D4           ; *4
         adda.l d4,a3
         subq.l #1,d4     ;b <- 2*i-1
         move.l A2,D1
         bra.b .l4

.longdiv
         swap d0
         move.w d0,d7
         divu.w d4,d7
         swap d7
         move.w d7,d0
         swap d0
         divu.w d4,d0

         move.w d0,d7
         exg d0,d7
         clr.w d7
         swap d7
         move.w d7,(a3)     ;r[i] <- d%b
         bra.b .enddiv

.l2
         sub.l d0,d5
         sub.l d7,d5
         lsr.l #1,d5
.l4
         move.w -(a3),d0      ; r[i]
         mulu.w d1,d0       ;r[i]*10000
         add.l d0,d5       ;d += r[i]*10000
         move.l d5,d0
         divu.w d4,d0
         bvs.s .longdiv

         move.w d0,d7
         clr.w d0
         swap d0
         move.w d0,(a3)     ;r[i] <- d%b
.enddiv
         subq.l #2,d4    ;i <- i - 1
         bcc.b .l2       ;the main loop
         divu.w d1,d5
 
         add.w (SP),D5 ; cv
         move.l D5,(SP) ; cv
         bsr.b PR0000
         subq.l #7,d6   ;kv
         bne.b .l0
         addq.l #4,SP ;  restore stack

         exg a5,a6
         moveq #INTB_VERTB,d0
         move.l SP,A1
         jsr RemIntServer(a6)
         jsr Permit(a6)
        exg a5,a6
        lea     22(SP),SP                ; restore stack (is_Size)
 
        movem.l (A4),D1/D5        ; last use of cout and time
	move.l	a4,d2			; buffer

	move.b	VBlankFrequency(a5),d6	; d6.l is 0
	move.l	d6,d0
	add.w	d0,d0
	divu.w	d0,d5			; d5 = seconds
	move.l	d5,d4
	swap	d4
	mulu.w	#100,d4
	add.l	d4,d6			; round up (+0.5)
	divu.w	d0,d6			; d6 = 1/100ths
        moveq   #10,D0

	move.b	#' ',(a4)+

	moveq	#0,d4			; skip leading zeroes
        move.l  A2,D7	                ; 10000
	bsr.b	SPrintTime

	move.b	#'.',(a4)+

	moveq	#'0',d4			; print leading zeroes
	move.w	d6,d5
	moveq	#10,d7
	bsr.b	SPrintTime

	move.b	d0,(a4)+		; newline

	move.l	a4,d3
	sub.l	d2,d3
	jsr	Write(a6)

	move.l	a6,a1
	move.l	a5,a6
	jmp	CloseLibrary(a6)	; END OF PROGRAM

SPrintTime	; d5=value, a4=buffer
.Next	ext.l	d5
	divu.w	d7,d5
	cmp.b	d4,d5
	beq.b	.LeadZero
	moveq	#'0',d4
	add.b	d4,d5
	move.b	d5,(a4)+
.LeadZero
	swap	d5
	divu.w	d0,d7
	bne.b	.Next
	rts

PR0000     ;prints d5, uses a0,a1(scratch),d0,d1,d2,d3
      moveq #4,D3
      moveq #buf-cout,D2
        move.w	#$0100,a0
	move.l	#$2f3a2f2f,d0
	move.w	#1000,d1
.b1000	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b1000
	add.w	d1,d5

	moveq	#100,d1
.b100	addq.b	#1,d0
	sub.w	d1,d5
	bcc.b	.b100
	add.w	d1,d5

	swap	d0
	moveq	#10,d1
.b10	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b10
	add.b	d5,d0

        move.l D0,buf-cout(A4) ; buf
writetext
        move.l (A4),D1    ; cout
        add.l  A4,D2 ; buf
        jmp Write(A6) ;call Write(stdout,buff,size)

; If interrupt priority is >= 10 then a0 must point at $dff000 on exit
rasteri
      addq.l #2,(a1)
      moveq #0,d0  ; must set Z flag on exit!
      rts

	cnop 0,4
cout dc.l 0
time dc.l 0
buf ds.b 4

; Overwritten code/data start here. 
workspace

msg1  dc.b 'number pi calculator v13',10
msg4 dc.b 'number of digits (up to '
msg5 dc.b ')? '
msg3 dc.b ' digits will be printed',10
msg2
      even

getnum
.error   moveq #msg4-cout,D2
         moveq #msg5-msg4,d3
;         bsr.b .write
	jsr	(a2)		; writetext
         move.w d7,d5
         bsr.w PR0000
         moveq #msg5-cout,D2
         moveq #msg3-msg5,d3
;         bsr.b .write
	jsr	(a2)		; writetext
        jsr Input(a6)          ;get stdin
        move.l d0,d1
        moveq #msg1-cout,D2
        add.l A4,D2
        moveq #4+1,d3     ;+ newline
        jsr Read(a6)
 
        move.l	d2,a0
	moveq	#0,d5
.loop	subq.w	#1,d0
	beq.b	.done
	move.w	#256-'0',d6
	add.b	(a0)+,d6
;	cmp.w	#9,d6
;	bhi.b	.error
	cmp.w	d4,d6		; digit >= 10?
	bhs.b	.error
	mulu.w	d4,d5		; *10
	add.w	d6,d5
	bra.b	.loop
.done
	cmp.w d7,d5
	bhi.b .error
	move.w d5,d1
	beq.b .error
	rts

libname  dc.b "dos.library",0

Buffy
     ds.b 65536-(Buffy-start)

; asm-one&co
;	PRINTV	Buffy-start+36		; 36 = hunk overhead
;	PRINTV	((65536-(workspace-start))/(7<<2))<<2
Nice, Amiga beated Atari ST again In number of digits. Not only PC in code density.
Don_Adan is offline  
Old 25 June 2021, 11:31   #344
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Quote:
Originally Posted by roondar View Post
Just for reference: what was the original size & speed of the program?
I'm loving all the optimisations I'm seeing and I'd like to put them in perspective after all the work that has gone into it
amiga1200-12 68020 54 820

820 bytes of exe.
Don_Adan is offline  
Old 25 June 2021, 11:40   #345
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,423
That's awesome!
Nearly 37% smaller - well done to all involved
roondar is offline  
Old 25 June 2021, 11:48   #346
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,043
The good new is... maxn be can further increased if you move everything from bsr getnum to lea workspace(pc),a3 into the getnum subroutine, in case that's an "important" metric.

The bad new is... Atari guys could just show up, and copy and adjust the code, and they'll be ahead again (their tos calls and fileformat have lower overhead, being more primitive, more close to 8-bit era).
a/b is offline  
Old 25 June 2021, 11:53   #347
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,423
Oh, I'm not seeing this as an Amiga vs Atari thing. For me it's mainly about seeing 68K optimisation in action. If the Atari guys use this and make their 68K version even smaller, all the better for any comparison between CPU architectures and relative code sizes
roondar is offline  
Old 25 June 2021, 12:37   #348
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
We can use 65520 for store maximum possible 2340 digits, but it will be unfair for 8 bit systems and Amiga exe will be a few bytes longest. For Atari ST exe size, i think this is dependent how long will be code for time calculation, maybe Atari ST has a few bytes shortest writetext routine.
Don_Adan is offline  
Old 25 June 2021, 13:58   #349
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
BTW. I forget that for newest kick (2.0+ if i remember right) we can use TaggedOpenLibrary call. Then Atari ST can have problem to beat Amiga exe size.

Code:
        moveq	#4,D0			; dos library
	jsr	-$32A(A6)		; TaggedOpenLibrary
Don_Adan is offline  
Old 25 June 2021, 15:12   #350
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,043
KS2.0 comes with a much better set of I/O calls than Read() and Write(), iirc Meynaf already suggested that but litwr didn't like the idea, said it breaks the rules or something to that extent and Read() and Write() have to be used (making the code larger).
a/b is offline  
Old 25 June 2021, 18:42   #351
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Quote:
Originally Posted by a/b View Post
KS2.0 comes with a much better set of I/O calls than Read() and Write(), iirc Meynaf already suggested that but litwr didn't like the idea, said it breaks the rules or something to that extent and Read() and Write() have to be used (making the code larger).
Perhaps point 2. of litwr rules "calculation of them", PR0000 routine. He was unhappy from my sub.w attempt without divu.w. Using TaggedOpenLibrary seems to be ok, and we can gain 14 bytes from Amiga program size, exactly 12 or 16.

"Every program is satisfying four restrictions: 1) it measures time; 2) it uses an OS function to print digits, it prints 4 digits a time synchronously with the calculation of them; 3) it uses less than 64 KB RAM for the code and data; 4) it utilizes all available RAM below 64 KB limit to get the maximum number of calculated digits, so it is forbidden to restrict artificially the maximum number of digits."

Last edited by Don_Adan; 25 June 2021 at 18:49.
Don_Adan is offline  
Old 25 June 2021, 22:16   #352
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,043
596 bytes (delayed permit/remint to more efficiently use a5/a6), plus some minor cosmetic work (badly needed ).

Code:
OldOpenLibrary = -408
CloseLibrary = -414
Output = -60
Input = -54
Write = -48
Read = -42
Forbid = -132
Permit = -138
AddIntServer = -168
RemIntServer = -174
VBlankFrequency = 530
INTB_VERTB = 5     ;for vblank interrupt
NT_INTERRUPT = 2   ;node type

;N = 7*D/2 ;D digits, e.g., N = 350 for 100 digits

start
         move.l 4.W,a5
         move.l a5,a6
         lea libname(pc),a1         ;open the dos library
         jsr OldOpenLibrary(a6)
         move.l d0,a6
         jsr Output(a6)          ;get stdout
         lea time(PC),A4
         lea rasteri(PC),A2
         move.l A2,-(SP)      ; is_Code
         move.l A4,-(SP)      ; is_Data
         clr.l -(SP)          ; ln_Name
         move.w #NT_INTERRUPT<<8+0,-(SP)	; ln_Type, ln_Pri
         subq.l #2*4,SP				; ln_Succ, ln_Pred

         move.l d0,-(A4)            ;cout
         move.w	#((65536-(workspace-start))/(7<<2))<<2,D7	; d7.w=maxn
         moveq #10,D4
	subq.l	#rasteri-writetext,a2		; a2=writetext
         moveq #msg1-cout,D2 ; must be checked if in moveq range, the longest text can be moved to end
         moveq #msg1end-msg1,d3
	jsr	(a2)		; writetext

         bsr.w getnum		; returns value in d1 and d5
         addq.w #3,d5
         and.w #$fffc,d5
         move.w d5,d6
         cmp.b (a0),d4		; only newline remaining?
         bne.b .l21
         cmp.w d1,d5
         beq.b .l7
.l21
         bsr.w PR0000
         moveq #msg4-cout,D2
         moveq #msg4end-msg4,d3
	jsr	(a2)		; writetext
.l7 
         mulu.w #7,d6          ;kv = d6
         lsr.l #2,D6           ;/4
         move.l d6,d7
         lea workspace(pc),a3

         exg a5,a6			; use exec
         jsr Forbid(a6)
         moveq #INTB_VERTB,d0
         move.l SP,A1
         jsr AddIntServer(a6)
         exg a5,a6			; use dos
 
         move.l #2000*65537,d0
         move.l a3,a0
.fill    move.l d0,(a0)+
         subq.l #1,D7
         bne.b .fill

         move.w #10000,A2
         clr.l -(SP)      ;cv <- 0

.l0      moveq #0,D5      ;d <- 0
         move.l d6,d4     ;i <- kv, i <- i*2
         lsl.l #2,D4      ;*4
         adda.l d4,a3
         subq.l #1,d4     ;b <- 2*i-1
         move.l A2,D1
         bra.b .l4

.longdiv
         swap d0
         move.w d0,d7
         divu.w d4,d7
         swap d7
         move.w d7,d0
         swap d0
         divu.w d4,d0

         move.w d0,d7
         exg d0,d7
         clr.w d7
         swap d7
         move.w d7,(a3)     ;r[i] <- d%b
         bra.b .enddiv
.l2
         sub.l d0,d5
         sub.l d7,d5
         lsr.l #1,d5
.l4
         move.w -(a3),d0    ;r[i]
         mulu.w d1,d0       ;r[i]*10000
         add.l d0,d5        ;d += r[i]*10000
         move.l d5,d0
         divu.w d4,d0
         bvs.s .longdiv

         move.w d0,d7
         clr.w d0
         swap d0
         move.w d0,(a3)     ;r[i] <- d%b
.enddiv
         subq.l #2,d4       ;i <- i-1
         bcc.b .l2          ;the main loop
         divu.w d1,d5       ;/10000
 
         add.w (SP),D5  ;cv
         move.l D5,(SP) ;cv
         bsr.b PR0000
         subq.l #7,d6   ;kv
         bne.b .l0

         addq.l #4,SP ;  restore stack

	movem.l	(a4)+,d1/d5		; last use of cout and time
	move.l	a4,d2			; buffer

	move.b	VBlankFrequency(a5),d6	; d6.l is 0
	move.l	d6,d0
	add.w	d0,d0
	divu.w	d0,d5			; d5 = seconds
	move.l	d5,d4
	swap	d4
	mulu.w	#100,d4
	add.l	d4,d6			; round up (+0.5)
	divu.w	d0,d6			; d6 = 1/100ths
        moveq   #10,D0

	move.b	#' ',(a4)+

	moveq	#0,d4			; skip leading zeroes
        move.l  A2,D7	                ; 10000
	bsr.b	SPrintTime

	move.b	#'.',(a4)+

	moveq	#'0',d4			; print leading zeroes
	move.w	d6,d5
	moveq	#10,d7
	bsr.b	SPrintTime

	move.b	d0,(a4)+		; newline

	move.l	a4,d3
	sub.l	d2,d3
	jsr	Write(a6)

        exg a5,a6			; use exec
        moveq #INTB_VERTB,d0
        move.l SP,A1
        jsr RemIntServer(a6)
        jsr Permit(a6)
        lea     22(SP),SP               ; restore stack (is_Size)

	move.l	a5,a1
	jmp	CloseLibrary(a6)	; close dos
					; END OF PROGRAM

SPrintTime	; d5=value, a4=buffer
.Next	ext.l	d5
	divu.w	d7,d5
	cmp.b	d4,d5
	beq.b	.LeadZero
	moveq	#'0',d4
	add.b	d4,d5
	move.b	d5,(a4)+
.LeadZero
	swap	d5
	divu.w	d0,d7
	bne.b	.Next
	rts

PR0000     ;prints d5, uses a0,a1(scratch),d0,d1,d2,d3
        moveq #buf-cout,D2
        moveq #4,D3
        move.w	#$0100,a0
	move.l	#$2f3a2f2f,d0
	move.w	#1000,d1
.b1000	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b1000
	add.w	d1,d5

	moveq	#100,d1
.b100	addq.b	#1,d0
	sub.w	d1,d5
	bcc.b	.b100
	add.w	d1,d5

	swap	d0
	moveq	#10,d1
.b10	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b10
	add.b	d5,d0

        move.l D0,buf-cout(A4)
writetext
        move.l (A4),D1			; cout
        add.l  A4,D2			; buff
        jmp Write(A6) 			; call Write(stdout,buffer,size)

; If interrupt priority is >= 10 then a0 must be set to $dff000 on exit
rasteri
      addq.l #2,(a1)
      moveq #0,d0 			; must set Z flag on exit!
      rts

	cnop 0,4
cout dc.l 0
time dc.l 0
buf ds.b 4

; Overwritten code/data starts here. 
workspace

msg1 dc.b 'number pi calculator v14',10		; odd length
msg1end
msg2 dc.b 'number of digits (up to '		; even length
msg2end
msg3 dc.b ')? '					; odd length
msg3end
msg4 dc.b ' digits will be printed',10		; even length
msg4end
	even

getnum
.error  moveq #msg2-cout,D2
        moveq #msg2end-msg2,d3
	jsr	(a2)		; writetext
        move.w d7,d5
        bsr.w PR0000
        moveq #msg3-cout,D2
        moveq #msg3end-msg3,d3
	jsr	(a2)		; writetext
        jsr Input(a6)          ;get stdin
        move.l d0,d1
        moveq #msg1-cout,D2
        add.l A4,D2
        moveq #4+1,d3     ;+ newline
        jsr Read(a6)
 
        move.l	d2,a0
	moveq	#0,d5
.loop	subq.w	#1,d0
	beq.b	.done
	move.w	#256-'0',d6
	add.b	(a0)+,d6
	cmp.w	d4,d6		; digit >= 10?
	bhs.b	.error
	mulu.w	d4,d5		; *10
	add.w	d6,d5
	bra.b	.loop
.done
	cmp.w d7,d5
	bhi.b .error
	move.w d5,d1
	beq.b .error
	rts

libname  dc.b "dos.library",0

Buffy
     ds.b 65536-(Buffy-start)

; asm-one&co
;	PRINTV	Buffy-start+36		; 36 = hunk overhead
;	PRINTV	((65536-(workspace-start))/(7<<2))<<2

Last edited by a/b; 25 June 2021 at 23:48. Reason: making it more even
a/b is offline  
Old 25 June 2021, 23:33   #353
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Very good, but why you used movem.l (A4)+,D1/D5? movem.l (A4),D1/D5 looks better for me, you dont trash workspace area later, even if this is not important. And i always prefer to use "even" after text part and before code. Someone can change text and it cant assemble without source fixing.
Don_Adan is offline  
Old 25 June 2021, 23:55   #354
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,043
I was experimenting with text and moving it around, and accidentalled the trailing "even" in the process ;P. Fixed now.

The reason for a4 postinc is the interrupt is still active (it's removed just before exiting so there's no need to swap a5 and a6 several times), and you don't want it to trigger right when you are printing the time and poop over the buffer, so now the print buffer is 8 bytes futher down.
a/b is offline  
Old 26 June 2021, 01:58   #355
Bruce Abbott
Registered User
 
Bruce Abbott's Avatar
 
Join Date: Mar 2018
Location: Hastings, New Zealand
Posts: 2,656
Quote:
Originally Posted by Don_Adan View Post
Using TaggedOpenLibrary seems to be ok,
I disagree. It restricts the program to KS2+ and so excludes my KS1.3 A500. Therefore I will have no 68000 based system to test it on.

Also AFAIK TaggedOpenLibrary is undocumented, at least up to OS3.5. It may not be against the rules exactly, but... Hey! I just thought of a cool new function for the next version of Amiga OS - it's called PiPrintDigits!
Bruce Abbott is offline  
Old 26 June 2021, 02:54   #356
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Hmm, is it me or is DOSBase at -$148(a2) when program is executed from dos?
(Tested in 1.3 and 3.1)

Last edited by alkis; 26 June 2021 at 03:02. Reason: forgot the $ at 148
alkis is offline  
Old 26 June 2021, 03:20   #357
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Yeap, this works.
Compile to disk. Run from shell.

Simple echo, compile to foo, run "foo 1234", displays 1234

Code:
	
        include libraries/dos_lib.i

	lea.l	-$148(a2),a6
	move.l	a0,d2
	move.l	d0,d3
	
	jsr	_LVOOutput(a6)
	move.l	d0,d1
	
	jsr	_LVOWrite(a6)
	
	moveq.l	#0,d0
	rts
alkis is offline  
Old 26 June 2021, 07:53   #358
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Quote:
Originally Posted by a/b View Post
I was experimenting with text and moving it around, and accidentalled the trailing "even" in the process ;P. Fixed now.

The reason for a4 postinc is the interrupt is still active (it's removed just before exiting so there's no need to swap a5 and a6 several times), and you don't want it to trigger right when you are printing the time and poop over the buffer, so now the print buffer is 8 bytes futher down.
Ok, i forget about moved end code.
Don_Adan is offline  
Old 26 June 2021, 08:01   #359
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Quote:
Originally Posted by Bruce Abbott View Post
I disagree. It restricts the program to KS2+ and so excludes my KS1.3 A500. Therefore I will have no 68000 based system to test it on.

Also AFAIK TaggedOpenLibrary is undocumented, at least up to OS3.5. It may not be against the rules exactly, but... Hey! I just thought of a cool new function for the next version of Amiga OS - it's called PiPrintDigits!
This was originally 68020+ version (check changed thread name) , but due no 68020 instructions and no odd data accesesses works on 68000 too. Every Amiga with 68000 can have KS2+. If you checked litwr benchmarks table, then different Amiga versions for 68000 and for 68020 are mentioned. We can have 2 different version too, also 68000 version originally used mulu 10000 emulation code for speed.
TaggedOpenLibrary is private exec call, but is safe to use for KS2+.

Last edited by Don_Adan; 26 June 2021 at 08:07.
Don_Adan is offline  
Old 26 June 2021, 09:32   #360
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 2,010
Then the shortest Amiga version, can looks next:

Code:
OldOpenLibrary = -408
CloseLibrary = -414
Output = -60
Input = -54
Write = -48
Read = -42
Forbid = -132
Permit = -138
AddIntServer = -168
RemIntServer = -174
VBlankFrequency = 530
INTB_VERTB = 5     ;for vblank interrupt
NT_INTERRUPT = 2   ;node type

;N = 7*D/2 ;D digits, e.g., N = 350 for 100 digits

start
         move.l 4.W,a5
         move.l a5,a6
         moveq	#4,D0			; dos library
         jsr	-$32A(A6)		; TaggedOpenLibrary
         move.l d0,a6
         jsr Output(a6)          ;get stdout
         lea time(PC),A4
         lea rasteri(PC),A2
         move.l A2,-(SP)      ; is_Code
         move.l A4,-(SP)      ; is_Data
         clr.l -(SP)          ; ln_Name
         move.w #NT_INTERRUPT<<8+0,-(SP)	; ln_Type, ln_Pri
         subq.l #2*4,SP				; ln_Succ, ln_Pred

         move.l d0,-(A4)            ;cout
         move.w	#((65536-(workspace-start))/(7<<2))<<2,D7	; d7.w=maxn
         moveq #10,D4
	subq.l	#rasteri-writetext,a2		; a2=writetext
         moveq #msg1-cout,D2 ; must be checked if in moveq range, the longest text can be moved to end
         moveq #msg1end-msg1,d3
	jsr	(a2)		; writetext

         bsr.w getnum		; returns value in d1 and d5
         addq.w #3,d5
         and.w #$fffc,d5
         move.w d5,d6
         cmp.b (a0),d4		; only newline remaining?
         bne.b .l21
         cmp.w d1,d5
         beq.b .l7
.l21
         bsr.w PR0000
         moveq #msg4-cout,D2
         moveq #msg4end-msg4,d3
	jsr	(a2)		; writetext
.l7 
         mulu.w #7,d6          ;kv = d6
         lsr.l #2,D6           ;/4
         move.l d6,d7
         lea workspace(pc),a3

         exg a5,a6			; use exec
         jsr Forbid(a6)
         moveq #INTB_VERTB,d0
         move.l SP,A1
         jsr AddIntServer(a6)
         exg a5,a6			; use dos
 
         move.l #2000*65537,d0
         move.l a3,a0
.fill    move.l d0,(a0)+
         subq.l #1,D7
         bne.b .fill

         move.w #10000,A2
         clr.l -(SP)      ;cv <- 0

.l0      moveq #0,D5      ;d <- 0
         move.l d6,d4     ;i <- kv, i <- i*2
         lsl.l #2,D4      ;*4
         adda.l d4,a3
         subq.l #1,d4     ;b <- 2*i-1
         move.l A2,D1
         bra.b .l4

.longdiv
         swap d0
         move.w d0,d7
         divu.w d4,d7
         swap d7
         move.w d7,d0
         swap d0
         divu.w d4,d0

         move.w d0,d7
         exg d0,d7
         clr.w d7
         swap d7
         move.w d7,(a3)     ;r[i] <- d%b
         bra.b .enddiv
.l2
         sub.l d0,d5
         sub.l d7,d5
         lsr.l #1,d5
.l4
         move.w -(a3),d0    ;r[i]
         mulu.w d1,d0       ;r[i]*10000
         add.l d0,d5        ;d += r[i]*10000
         move.l d5,d0
         divu.w d4,d0
         bvs.s .longdiv

         move.w d0,d7
         clr.w d0
         swap d0
         move.w d0,(a3)     ;r[i] <- d%b
.enddiv
         subq.l #2,d4       ;i <- i-1
         bcc.b .l2          ;the main loop
         divu.w d1,d5       ;/10000
 
         add.w (SP),D5  ;cv
         move.l D5,(SP) ;cv
         bsr.b PR0000
         subq.l #7,d6   ;kv
         bne.b .l0

         addq.l #4,SP ;  restore stack

	movem.l	(a4)+,d1/d5		; last use of cout and time
	move.l	a4,d2			; buffer

	move.b	VBlankFrequency(a5),d6	; d6.l is 0
	move.l	d6,d0
	add.w	d0,d0
	divu.w	d0,d5			; d5 = seconds
	move.l	d5,d4
	swap	d4
	mulu.w	#100,d4
	add.l	d4,d6			; round up (+0.5)
	divu.w	d0,d6			; d6 = 1/100ths
        moveq   #10,D0

	move.b	#' ',(a4)+

	moveq	#0,d4			; skip leading zeroes
        move.l  A2,D7	                ; 10000
	bsr.b	SPrintTime

	move.b	#'.',(a4)+

	moveq	#'0',d4			; print leading zeroes
	move.w	d6,d5
	moveq	#10,d7
	bsr.b	SPrintTime

	move.b	d0,(a4)+		; newline

	move.l	a4,d3
	sub.l	d2,d3
	jsr	Write(a6)

        exg a5,a6			; use exec
        moveq #INTB_VERTB,d0
        move.l SP,A1
        jsr RemIntServer(a6)
        jsr Permit(a6)
        lea     22(SP),SP               ; restore stack (is_Size)

	move.l	a5,a1
	jmp	CloseLibrary(a6)	; close dos
					; END OF PROGRAM

SPrintTime	; d5=value, a4=buffer
.Next	ext.l	d5
	divu.w	d7,d5
	cmp.b	d4,d5
	beq.b	.LeadZero
	moveq	#'0',d4
	add.b	d4,d5
	move.b	d5,(a4)+
.LeadZero
	swap	d5
	divu.w	d0,d7
	bne.b	.Next
	rts

PR0000     ;prints d5, uses a0,a1(scratch),d0,d1,d2,d3
        moveq #buf-cout,D2
        moveq #4,D3
        move.w	#$0100,a0
	move.l	#$2f3a2f2f,d0
	move.w	#1000,d1
.b1000	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b1000
	add.w	d1,d5

	moveq	#100,d1
.b100	addq.b	#1,d0
	sub.w	d1,d5
	bcc.b	.b100
	add.w	d1,d5

	swap	d0
	moveq	#10,d1
.b10	add.w	a0,d0
	sub.w	d1,d5
	bcc.b	.b10
	add.b	d5,d0

        move.l D0,buf-cout(A4)
writetext
        move.l (A4),D1			; cout
        add.l  A4,D2			; buff
        jmp Write(A6) 			; call Write(stdout,buffer,size)

; If interrupt priority is >= 10 then a0 must be set to $dff000 on exit
rasteri
      addq.l #2,(a1)
      moveq #0,d0 			; must set Z flag on exit!
      rts

	cnop 0,4
cout dc.l 0
time dc.l 0
buf ds.b 4

; Overwritten code/data starts here. 
workspace

msg1 dc.b 'number pi calculator v14',10		; odd length
msg1end
msg2 dc.b 'number of digits (up to '		; even length
msg2end
msg3 dc.b ')? '					; odd length
msg3end
msg4 dc.b ' digits will be printed',10		; even length
msg4end
	even

getnum
.error  moveq #msg2-cout,D2
        moveq #msg2end-msg2,d3
	jsr	(a2)		; writetext
        move.w d7,d5
        bsr.w PR0000
        moveq #msg3-cout,D2
        moveq #msg3end-msg3,d3
	jsr	(a2)		; writetext
        jsr Input(a6)          ;get stdin
        move.l d0,d1
        moveq #msg1-cout,D2
        add.l A4,D2
        moveq #4+1,d3     ;+ newline
        jsr Read(a6)
 
        move.l	d2,a0
	moveq	#0,d5
.loop	subq.w	#1,d0
	beq.b	.done
	move.w	#256-'0',d6
	add.b	(a0)+,d6
	cmp.w	d4,d6		; digit >= 10?
	bhs.b	.error
	mulu.w	d4,d5		; *10
	add.w	d6,d5
	bra.b	.loop
.done
	cmp.w d7,d5
	bhi.b .error
	move.w d5,d1
	beq.b .error
	rts

Buffy
     ds.b 65536-(Buffy-start)
Or Alkis idea can be used.

Last edited by Don_Adan; 26 June 2021 at 15:18.
Don_Adan is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
68020 Bit Field Instructions mcgeezer Coders. Asm / Hardware 9 27 October 2023 23:21
68060 64-bit integer math BSzili Coders. Asm / Hardware 7 25 January 2021 21:18
Discovery: Math Audio Snow request.Old Rare Games 30 20 August 2018 12:17
Math apps mtb support.Apps 1 08 September 2002 18:59

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 06:23.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10527 seconds with 14 queries