English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 02 June 2022, 12:51   #1
hop
Registered User
 
Join Date: Apr 2019
Location: UK
Posts: 172
Assembly language switch statement

I've written a bootblock trackdisk hunk loadfile loader as an exercise. The routine that iterates over the blocks really needs a (C/C++) switch statement. This is the best I could come up with in 68k - is there a more elegant way to implement this or is this the standard pattern? Thanks.

Code:
; ---------------------------------------------------------------------------
; Iterate over all the blocks in the file.
; A hunk file is just a set of blocks. 
; Hunks are made of a number of blocks. 
; See Amiga Guru Book section 22.1.
;
; Modifies: Lots!
;
loadBlocks:
	moveq #0,d4	; current byte offset into RootHunks array = currentIndex * sizeof(RootHunk)
.blockLoop
	; The total number of blocks in a load file is not known; The header contains the number of 
	; "root" hunks (CODE, DATA), but there may be other hunks e.g. RELOC hunks
	; Just have to iterate over the binary to the end.
	move.l a5,d0			; D0 <- readOffsetBytes
	; TODO: assert(readOffsetBytes<=loadFileSizeBytes)
	cmp.l #loadFileSizeBytes,d0	; set flags from readOffsetBytes-loadFileSizeBytes
	beq.b .end			; Z set if readOffsetBytes==loadFileSizeBytes

	; Each block start with a longword identifier.
	;
	; Note that with the exception of the first hunk, HUNK_HEADER, only the lower 29 bits of the leading ID are used.
	; The three most significant bits are used to indicate:
	;   (i)  what type of memory to use for the hunk containing this block, and 
	;   (ii) whether the block can be ignored
	; 
	; Load modules will have a HUNK_HEADER block which contains the memory type to be used for each segment.
	; Object modules do not contain a HUNK_HEADER block, and this information is not in the HUNK_UNIT either so 
	; it is packed into the block type ULONG
	; See The AmigaDOS Manual - 3rd edition, p357

	bsr.w readLongIntoD0
	andi.l #$1fffffff,d0	; strip top 3 bits just in case. D0 = blockType

	; switch (blockType)  TODO: Replace with jump table?
	cmpi.w #HUNK_CODE,d0		; $3E9
	bne.b .notHUNK_CODE
	pea .blockLoop(pc)		; push return address for RTS inside subsequent call
	bra.w loadHUNK_CODEorDATA	; use BRA instead of BSR so doesn't push return address
.notHUNK_CODE
	cmpi.w #HUNK_DATA,d0	; $3EA
	bne.b .notHUNK_DATA
	pea .blockLoop(pc)
	bra.w loadHUNK_CODEorDATA
.notHUNK_DATA
	cmpi.w #HUNK_BSS,d0	; $3EB
	bne.b .notHUNK_BSS
	pea .blockLoop(pc)
	bra.w loadHUNK_BSS
.notHUNK_BSS
	cmpi.w #HUNK_RELOC32,d0	; $3EC
	bne.b .notHUNK_RELOC32
	pea .blockLoop(pc)
	bra.w processHUNK_RELOC32
.notHUNK_RELOC32
	cmpi.w #HUNK_END,d0	; $3F2
	beq.b .blockLoop	; HUNK_END is just the longword identifer. Nothing to do

	; Unhandled block type
	bra.w error	

.end	rts
hop is offline  
Old 02 June 2022, 14:00   #2
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
Personally, I like using a jump table like this:
Code:
; make sure to limit d0 to range of 0 to n before this code executes 
; (where n = default in case of unhandled block type)

; if using 68020+ replace the add.w's with scaling *4 instead
   add.w   d0,d0
   add.w   d0,d0
   jmp   .jmp_table(pc,d0.w)

.jmp_table
   bra.w   .notHUNK_CODE
   bra.w   .notHUNK_DATA
   bra.w   .notHUNK_BSS
   ; etc
   <<default case code>>

.notHUNK_CODE
   <<do stuff>>
roondar is offline  
Old 02 June 2022, 15:07   #3
Asman
68k
 
Asman's Avatar
 
Join Date: Sep 2005
Location: Somewhere
Posts: 828
@hop

you can use something like that

Code:
;in
;	d0 - hunk value like $3e9,...

Hunks:
		moveq	#(end_table-table)/4-1,d2
		lea	(end_table,pc),a0

.loop		move.l	-(a0),d1
		cmp.w	d1,d0	
		bne.b	.next

		swap	d1
		jmp	(a0,d1.w)

.next		dbf	d2,.loop 

	;handle unsupported hunk value here

		rts

HUNK_CODE	= $3e9
HUNK_DATA	= $3ea

table:
		dc.w	doHunkCode-*,HUNK_CODE
		dc.w	doHunkData-*,HUNK_DATA

		;you can use dr.w doHunkCode,HUNK_CODE if your assembler supports it
end_table

doHunkCode:
		rts
doHunkData:
		rts
Asman is offline  
Old 02 June 2022, 15:49   #4
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
Also (several conditions, but in some cases they are all true), if there's only a small number of cmps to be made and/or you don't want to use a jmp table, and the numbers are close to each others, and you don't have to preserve them, you can do a sub and then chain subq/addq (shorter/faster) instead of a list of cmps.
And another thing, in Roondar's example (yup, that's how you typicallly do those things). Depending on your assembler, bra.w table can be problematic if you let it do optimizations because it can change (some of) them to 8-bit bra.b (or .s, depending on your style) and cause your code to explode. So, if you are considering that scenario, jmp offset(pc) is safer (same speed and instruction length).
a/b is offline  
Old 02 June 2022, 16:21   #5
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
Quote:
Originally Posted by a/b View Post
And another thing, in Roondar's example (yup, that's how you typicallly do those things). Depending on your assembler, bra.w table can be problematic if you let it do optimizations because it can change (some of) them to 8-bit bra.b (or .s, depending on your style) and cause your code to explode. So, if you are considering that scenario, jmp offset(pc) is safer (same speed and instruction length).
Ah, that's a cool little trick, I didn't realise jmp offset(pc) is the same speed as bra.w, but that is indeed true. I might change to that to safer. Just because I've not run into issues with my assembler setup doesn't mean someone else won't
roondar is offline  
Old 02 June 2022, 16:31   #6
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,196
Asman your method scans all values so complexity is O(n) whereas jump table complexity is O(1)

Better check for min/max then jump using jump table.
jotd is offline  
Old 02 June 2022, 16:32   #7
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
I'd do something like this:

Code:
	include	doshunks.i

	bsr readLongIntoD0

	cmpi.w	#HUNK_BREAK,d0
	bhi.b	unsupported_hunk
	subi.w	#HUNK_UNIT,d0
	bmi.b	unsupported_hunk
	add.w	d0,d0
	move.w	(hunk_j_table,pc,d0.w),d0
	jmp	(unsupported_hunk,pc,d0.w)  ;or jsr (depending on your process_ code)

hunk_j_table
	dc.w	process_HUNK_UNIT-unsupported_hunk
	dc.w	process_HUNK_NAME-unsupported_hunk
	dc.w	process_HUNK_CODE-unsupported_hunk
	dc.w	process_HUNK_DATA-unsupported_hunk
	dc.w	process_HUNK_BSS-unsupported_hunk
	dc.w	process_HUNK_RELOC32-unsupported_hunk
	dc.w	process_HUNK_RELOC16-unsupported_hunk
	dc.w	process_HUNK_RELOC8-unsupported_hunk
	dc.w	process_HUNK_EXT-unsupported_hunk
	dc.w	process_HUNK_SYMBOL-unsupported_hunk
	dc.w	process_HUNK_DEBUG-unsupported_hunk
	dc.w	process_HUNK_END-unsupported_hunk
	dc.w	process_HUNK_HEADER-unsupported_hunk
	dc.w	process_HUNK_OVERLAY-unsupported_hunk
	dc.w	process_HUNK_BREAK-unsupported_hunk

unsupported_hunk
process_HUNK_UNIT
process_HUNK_NAME
process_HUNK_RELOC16
process_HUNK_RELOC8
process_HUNK_EXT
process_HUNK_SYMBOL
process_HUNK_DEBUG
process_HUNK_OVERLAY
process_HUNK_BREAK
;	<<error or whatever>>

process_HUNK_CODE
process_HUNK_DATA
;	<<relocatable hunk>>

process_HUNK_BSS
;	<<bss hunk>>

process_HUNK_RELOC32
;	<<reloc table>>

process_HUNK_END
;	<<end exe>>

process_HUNK_HEADER
; ....
Generic, protected, fast
ross is offline  
Old 02 June 2022, 17:00   #8
Asman
68k
 
Asman's Avatar
 
Join Date: Sep 2005
Location: Somewhere
Posts: 828
@jotd

Yes, this is just example how to handle switch in other way than spagetti code of cmp/bcc.
Asman is offline  
Old 02 June 2022, 23:20   #9
hop
Registered User
 
Join Date: Apr 2019
Location: UK
Posts: 172
Thanks. I'll try some of these out.
hop is offline  
Old 03 June 2022, 12:16   #10
hop
Registered User
 
Join Date: Apr 2019
Location: UK
Posts: 172
Quote:
Originally Posted by ross View Post
I'd do something like this
Generic, protected, fast
Very elegant. Adapted and all working - many thanks.
hop 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
Fast switch statement code Jobbo Coders. Asm / Hardware 10 22 October 2021 19:13
MC68000 Assembly Language Support apex Coders. Asm / Hardware 1 06 August 2021 19:16
for..each statement in CLI pieter1976 support.Other 10 09 January 2020 22:15
A1200 and assembly language aricz Coders. General 16 08 February 2011 12:31
HELP with german language and installation of a aga-rtg switch by Multimedia Design keropi support.Hardware 9 05 January 2006 22:41

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 10:20.

Top

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