summaryrefslogtreecommitdiff
path: root/acorn/match.s
diff options
context:
space:
mode:
Diffstat (limited to 'acorn/match.s')
-rw-r--r--acorn/match.s217
1 files changed, 217 insertions, 0 deletions
diff --git a/acorn/match.s b/acorn/match.s
new file mode 100644
index 0000000..ee68ce6
--- /dev/null
+++ b/acorn/match.s
@@ -0,0 +1,217 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; match.s for ARM by Sergio Monesi.
+
+r0 RN 0
+r1 RN 1
+r2 RN 2
+r3 RN 3
+r4 RN 4
+r5 RN 5
+r6 RN 6
+r7 RN 7
+r8 RN 8
+r9 RN 9
+sl RN 10
+fp RN 11
+ip RN 12
+sp RN 13
+lr RN 14
+pc RN 15
+
+MAX_DIST EQU 32506
+WMASK EQU 32767
+MAX_MATCH EQU 258
+
+ AREA |C$$code|, CODE, READONLY
+
+
+; r1 = chain_lenght
+; r2 = scan
+; r3 = match
+; r4 = len (tmp)
+; r5 = best_len
+; r6 = limit
+; r7 = strend
+; r8 = scan_end1
+; r9 = scan_end
+; lr = window
+; fp = prev
+
+|__max_chain_length|
+ IMPORT max_chain_length
+ DCD max_chain_length
+|__window|
+ IMPORT window
+ DCD window
+|__prev|
+ IMPORT prev
+ DCD prev
+|__prev_length|
+ IMPORT prev_length
+ DCD prev_length
+|__strstart|
+ IMPORT strstart
+ DCD strstart
+|__good_match|
+ IMPORT good_match
+ DCD good_match
+|__nice_match|
+ IMPORT nice_match
+ DCD nice_match
+|__match_start|
+ IMPORT match_start
+ DCD match_start
+
+ DCB "longest_match"
+ DCB &00,&00,&00
+ DCD &ff000010
+
+ EXPORT longest_match
+longest_match
+ STMFD sp!, {r4-r9,fp,lr}
+
+ LDR fp, [pc, #|__prev|-.-8]
+
+ LDR r1, [pc, #|__max_chain_length|-.-8]
+ LDR r1, [r1]
+ LDR lr, [pc, #|__window|-.-8]
+
+ LDR ip, [pc, #|__strstart|-.-8]
+ LDR ip, [ip]
+ ADD r2, lr, ip
+ LDR r5, [pc, #|__prev_length|-.-8]
+ LDR r5, [r5]
+ SUBS ip, ip, #MAX_DIST-250 ; if r6 > MAX_DIST
+ SUBCSS r6, ip, #250 ; r6 = r6 - MAXDIST
+ MOVLS r6, #0 ; else r6 = 0
+
+ ADD r7, r2, #MAX_MATCH-256
+ ADD r7, r7, #256 ; r7 = r2 + MAX_MATCH (=258);
+
+ SUB ip, r5, #1
+ LDRB r8, [r2, ip]
+ LDRB r9, [r2, r5]
+
+ LDR ip, [pc, #|__good_match|-.-8]
+ LDR ip, [ip]
+ CMP r5, ip
+ MOVCS r1, r1, LSR #2
+
+cycle
+ ADD r3, lr, r0
+
+ LDRB ip, [r3, r5]
+ CMP ip, r9
+ BNE cycle_end
+
+ SUB ip, r5, #1
+ LDRB ip, [r3, ip]
+ CMP ip, r8
+ BNE cycle_end
+
+ LDRB ip, [r2]
+ LDRB r4, [r3]
+ CMP ip, r4
+ BNE cycle_end
+
+ LDRB ip, [r3, #1]
+ LDRB r4, [r2, #1]
+ CMP ip, r4
+ BNE cycle_end
+
+ ADD r2, r2, #2
+ ADD r3, r3, #2
+
+inn_cycle
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ CMP r2, r7
+ BCC inn_cycle
+
+exit_inn_cycle
+ SUB r4, r2, r7 ; len = MAX_MATCH - (int)(strend - scan);
+ ADD r4, r4, #MAX_MATCH-256
+ ADD r4, r4, #256
+
+ SUB r2, r2, r4 ; scan = strend - MAX_MATCH
+
+ CMP r4, r5 ; if (len > best_len) {
+ BLE cycle_end
+
+ LDR ip, [pc, #|__match_start|-.-8] ; match_start = cur_match;
+ STR r0, [ip]
+ MOV r5, r4 ; best_len = len;
+
+ LDR ip, [pc, #|__nice_match|-.-8] ; if (len >= nice_match)
+ LDR ip, [ip]
+ CMP r4, ip
+ BGE exit_match ; break;
+
+ SUB ip, r5, #1 ; scan_end1 = scan[best_len-1];
+ LDRB r8, [r2, ip]
+ LDRB r9, [r2, r5] ; scan_end = scan[best_len];
+
+cycle_end
+ MOV ip, r0, LSL #17 ; cur_match & WMASK
+ MOV ip, ip, LSR #17
+
+ LDR r0, [fp, ip, ASL #1] ; cur_match = prev[cur_match & WMASK]
+ MOV r0, r0, ASL #16
+ MOV r0, r0, LSR #16
+
+ CMP r0, r6 ; cur_match > limit
+ BLS exit_match
+ SUBS r1, r1, #1 ; --chain_length
+ BNE cycle ; chain_length != 0
+
+exit_match
+ MOV r0, r5
+
+ LDMFD sp!, {r4-r9,fp,pc}^
+
+ END