14 August 2021, 12:41 | #1 |
Registered User
Join Date: Feb 2019
Location: Zurich
Posts: 38
|
Can anyone make this code shorter?
I'm working with a Dragonball VZ CPU. It's got a built-in bootloader which allows you to operate the CPU remotely (with no RAM or ROM needed); this has a 32-byte buffer which you can use to upload code fragments which can then be executed.
I'm trying to write a code fragment which will read addresses and values from the serial port and write them to the internal registers. So far I've got this: Code:
loop: movq #4, %d7 lea insn+2, %a2 wait: movew RX, %d1 btstl #13, %d1 ; check for data being ready beqb wait moveb %d1, (%a2)+ ; received data is in the low byte dbf %d7, wait movew insn+4, %d1 beqb exit insn: movew #0x1234, 0x5678 ; overwritten with value and 16-bit target address brab loop exit: ; no return instruction needed Are there any clever tricks for making this fit within the 32-byte buffer? |
14 August 2021, 12:49 | #2 |
Registered User
Join Date: Jun 2015
Location: Germany
Posts: 1,918
|
Perhaps do the lea to a3 and then use a copy in the loop and later on 2(a3) instead of the insn+4.
|
14 August 2021, 13:02 | #3 |
Registered User
Join Date: Feb 2019
Location: Zurich
Posts: 38
|
Oops, I completely forgot to say --- this code loads at 0xffffffc0, so all addresses can be represented with a negative 16-bit value rather than needing a 32-bit address...
|
14 August 2021, 13:17 | #4 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,039
|
Is the loop actually executed 5 times (d7=4 -> dbf loops 5 times), or is that a typo? 5 times means you rewrite the first byte of brab loop.
If it's executed 4 times, you can replace "movew insn+4,%d1" with "tstw -(a2)" (or move to d1 if you need the value for later). Next... What are the replacement values for $5678? If they are within -$8000-$7fff you can try something like this (32 bytes): Code:
loop moveq #4-1,d7 wait move.w RX(pc),d1 ; or RX.w, no info on RX but since you said 36 bytes I guess it's either of these two btst #13,d1 beq.b wait lsl.l #8,d0 move.b d1,d0 dbf d7,wait tst.w d0 beq.b exit move.w d0,a2 swap d0 move.w d0,(a2) ; this works if a2 is within [-$8000,$7fff] bra.b loop exit Last edited by a/b; 14 August 2021 at 13:34. |
14 August 2021, 13:31 | #5 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
|
What is the effect of a write to address zero ? If it's no-op, then you can perform the write in all cases and do the loop afterwards, sparing a branch.
|
14 August 2021, 13:32 | #6 |
Registered User
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
|
Taking the above into account, and also moving the test to the end, results in a 32-byte version:
(edit: meynaf beat me to it ) Code:
loop: movq #4-1, %d7 lea insn+2, %a2 wait: movew RX.w, %d1 btstl #13, %d1 ; check for data being ready beqb wait moveb %d1, (%a2)+ ; received data is in the low byte dbf %d7, wait insn: movew #0x1234, 0x5678 ; overwritten with value and 16-bit target address tstw -(%a2) bneb loop exit: ; no return instruction needed |
14 August 2021, 14:19 | #7 |
Registered User
Join Date: Sep 2019
Location: Leicester / England
Posts: 201
|
If a write to 0x0000 isn't a no-op, I can get it down to 32 bytes, but you do need to write 6 bytes each time via the serial link... 0x31 0xfc (move instruction) followed by 2 bytes of immediate value and 2 bytes of data...
Devpac 68000 format (org and RX equ just so it assembles for testing): Code:
org $ffffffc0 RX equ $1234 ; Set this accordingly loop: moveq #6-1,d7 lea next(pc),a2 next: nop ; Overwritten with 0x31fc nop ; Overwritten with immediate value nop ; Overwritten with address wait: move.w RX.w,d1 btst.l #13,d1 beq.s wait move.b d1,(a2)+ dbf d7,wait tst.w -(a2) ; Test address bne.s loop exit: Code:
; Assumes RX is already defined loop: movq #6-1,%d7 lea next(%pc),%a2 next: nop ; Overwritten with 0x31fc nop ; Overwritten with immediate value nop ; Overwritten with address wait: movew RX.w,%d1 btstl #13,%d1 beqb wait moveb %d1,(%a2)+ dbf %d7,wait tstw -(%a2) ; Test address bneb loop exit: |
14 August 2021, 14:34 | #8 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
|
If write to 0 isn't acceptable, then it's still doable this way :
Code:
insn: move.w #$31fc,insn.w ; neutral - overwritten with value and 16-bit target address moveq #3,d7 lea insn+2(pc),a2 wait: move.w RX.w,d1 btst #13,d1 ; check for data being ready beq.b wait move.b d1,(a2)+ ; received data is in the low byte dbf d7,wait tst.w -(a2) bne.b insn |
14 August 2021, 14:54 | #9 |
Registered User
Join Date: Sep 2019
Location: Leicester / England
Posts: 201
|
Whilst having lunch, I realised you can still do it sending 4 bytes with the following minor adjustment which basically sets the move instruction to be the ocode of the move instruction on the first pass.
Code:
; Assumes RX is already defined loop: movq #3-1,%d7 lea next+2(%pc),%a2 next: movew #0x31fc,next.w ; Sets this instruction to what it currently is wait: movew RX.w,%d1 btstl #13,%d1 beqb wait moveb %d1,(%a2)+ dbf %d7,wait tstw -(%a2) ; Test address bneb loop exit: |
14 August 2021, 14:56 | #10 |
Registered User
Join Date: Sep 2019
Location: Leicester / England
Posts: 201
|
Which is what @meynaf has effectively posted
|
14 August 2021, 15:06 | #11 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
|
Is the code allowed to destroy itself ?
Because then we can do : Code:
insn: lea insn(pc),a2 loop: moveq #3,d7 wait: move.w RX.w,d1 btst #13,d1 ; check for data being ready beq.b wait move.b d1,(a2)+ ; received data is in the low byte dbf d7,wait movea.w -(a2),a1 ; address move.l a1,d1 ; tst.l a1 beq.b exit move.w -(a2),(a1) ; data bra.b loop exit: Of course, if writes to zero are allowed too, then extra branch is removed and it's done in 30 bytes |
14 August 2021, 15:47 | #12 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,039
|
Lunch break is over for me as well... Came up with another 2 or 4 bytes save in my code (=30 or 28 bytes):
1. -2: if you can use 4 bytes as a terminator, no need to tst.w d0 because swap will do that for free 2. -2: if you can have an arbitrary entry point (first instruction doesn't have to be the entry point) Code:
loop move.w d0,(a2) start_here moveq #4-1,d7 ; <= ENTRY POINT wait move.w RX.w,d1 ; this seems to be a general consensus btst #13,d1 beq.b wait lsl.l #8,d0 move.b d1,d0 dbf d7,wait move.w d0,a2 swap d0 ; d0.l = 0? bne.b loop |
14 August 2021, 23:45 | #13 |
Registered User
Join Date: Feb 2019
Location: Zurich
Posts: 38
|
Thanks very much --- that works fine!
Now I just need to work out why my much simpler memory fill routine always appears to hang the board after writing 205 bytes. It's not related as to where it's writing, as if I tell it to write to ROM it behaves exactly the same way, so it's not hitting an address trap of some kind... Code:
_start: lea 0x12345678, %a2 | address; placeholder value, replaced movl #0x12345678, %d7 | length; placeholder value, replaced loop: movb #0x88, (%a2)+ | value; placeholder value, replaced subql #1, %d7 bneb loop exit: |
16 August 2021, 08:10 | #14 | |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
|
Quote:
Code:
_start: lea 0x12345678, %a2 | address; placeholder value, replaced movl #0x12345678, %d7 | length; placeholder value, replaced movb #0x88, %d1 | value; placeholder value, replaced loop: movb %d1, (%a2)+ subql #1, %d7 bneb loop exit: |
|
17 August 2021, 23:39 | #15 |
Registered User
Join Date: Feb 2019
Location: Zurich
Posts: 38
|
That does indeed help --- but only very slightly. But I've managed to do some more debugging; it seems that when it crashes, my machine resets. (I laboriously wrote some code which intercepts the exception vectors and I can see it hit exception #0.)
The more I look into this the more confused I get. - it doesn't matter whether I'm writing to RAM or ROM. - if I write to the same address (i.e. by removing the + postincrement), it's fine. - adding a trivial delay loop (wait: movql #1, %d1; dbf %d1, wait) between writes causes it to die immediately. A wait value of 0 lets it succeed, but the magic number is still 205 bytes. - if I do 'movb %d1, (%a2); addql #1, %a2' then it behaves precisely as before (205 bytes). - if I do 'movb #0x88, %d1; ... movb %d1, (%a2); addql #1, %a2' I get 209 bytes. - if I do 'movb #0x88, %d1; ... movb %d1, (%a2)+' I get 209 bytes. - when the bootloader itself does a write, everything works fine! And I've disassembled that, and it's not touching any mysterious registers between writes --- the only thing it's doing is polling the uart for more data... This is increasingly less and less Amiga related, but... do 68000 machines tend to reset when a double fault occurs? (I can see in the data sheet that normally the CPU halts and waits for external input, which is normally no use to anyone.) |
18 August 2021, 00:15 | #16 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,959
|
Are you sure that your code dont overwrite/trash important data/code?
Maybe try move.l #205,D7 and later move.l #206,D7 and check output. |
18 August 2021, 05:16 | #17 | |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,039
|
Quote:
Also, exception #0 doesn't sound right. First two vectors are reset sp and pc. I don't know how limited is debugging in your case, can you display any info and/or have access to specific data like stack or register values...? I would start with setting the exception vectors 2-15 ($0008-$003c) to something like: Code:
vecX: move.w #$4000,$dff09a loopX: move.w #<COLOR>,$dff180 bra.b looopX |
|
18 August 2021, 08:31 | #18 |
Registered User
Join Date: Jun 2015
Location: Germany
Posts: 1,918
|
From what privilege level are you running that code?
|
18 August 2021, 11:25 | #19 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
|
My impression is that an interrupt comes for whatever reason and there is nothing to handle it -> crash.
If running in supervisor mode (i suppose it does, it's embedded thingy), then move.w #$2700,sr should clear that up. |
18 August 2021, 18:39 | #20 |
Registered User
Join Date: May 2004
Location: Somewhere secret
Age: 50
Posts: 364
|
Are you sure there is no kind of watchdog timer that you need to acknowledge? This behaviour seems odd...
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
how to make this code 68000 compliant? | jotd | Coders. Asm / Hardware | 2 | 30 January 2021 18:25 |
Do I have to change anything in the code to make BB2 work as AB3? | peceha | Coders. Blitz Basic | 4 | 22 June 2020 09:24 |
I am trying to make my first GFX assembler code | litwr | Coders. Tutorials | 111 | 14 December 2018 21:10 |
Make IDE cable shorter | Photon | support.Hardware | 10 | 21 August 2011 11:48 |
Another World - Amiga's version is shorter?? | Anubis | Retrogaming General Discussion | 13 | 06 May 2007 15:39 |
|
|