1// LzmaDecOpt.S -- ARM64-ASM version of LzmaDec_DecodeReal_3() function 2// 2021-04-25 : Igor Pavlov : Public domain 3 4/* 5; 3 - is the code compatibility version of LzmaDec_DecodeReal_*() 6; function for check at link time. 7; That code is tightly coupled with LzmaDec_TryDummy() 8; and with another functions in LzmaDec.c file. 9; CLzmaDec structure, (probs) array layout, input and output of 10; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM). 11*/ 12 13 14#include "7zAsm.S" 15 16 // .arch armv8-a 17 // .file "LzmaDecOpt.c" 18 .text 19 .align 2 20 .p2align 4,,15 21#ifdef __APPLE__ 22 .globl _LzmaDec_DecodeReal_3 23#else 24 .global LzmaDec_DecodeReal_3 25#endif 26 // .type LzmaDec_DecodeReal_3, %function 27 28// #define _LZMA_SIZE_OPT 1 29 30#define LZMA_USE_4BYTES_FILL 1 31// #define LZMA_USE_2BYTES_COPY 1 32// #define LZMA_USE_CMOV_LZ_WRAP 1 33// #define _LZMA_PROB32 1 34 35#define MY_ALIGN_FOR_ENTRY MY_ALIGN_32 36#define MY_ALIGN_FOR_LOOP MY_ALIGN_32 37#define MY_ALIGN_FOR_LOOP_16 MY_ALIGN_16 38 39#ifdef _LZMA_PROB32 40 .equ PSHIFT , 2 41 .macro PLOAD dest:req, mem:req 42 ldr \dest, [\mem] 43 .endm 44 .macro PLOAD_PREINDEXED dest:req, mem:req, offset:req 45 ldr \dest, [\mem, \offset]! 46 .endm 47 .macro PLOAD_2 dest:req, mem1:req, mem2:req 48 ldr \dest, [\mem1, \mem2] 49 .endm 50 .macro PLOAD_LSL dest:req, mem1:req, mem2:req 51 ldr \dest, [\mem1, \mem2, lsl #PSHIFT] 52 .endm 53 .macro PSTORE src:req, mem:req 54 str \src, [\mem] 55 .endm 56 .macro PSTORE_2 src:req, mem1:req, mem2:req 57 str \src, [\mem1, \mem2] 58 .endm 59 .macro PSTORE_LSL src:req, mem1:req, mem2:req 60 str \src, [\mem1, \mem2, lsl #PSHIFT] 61 .endm 62 .macro PSTORE_LSL_M1 src:req, mem1:req, mem2:req, temp_reg:req 63 // you must check that temp_reg is free register when macro is used 64 add \temp_reg, \mem1, \mem2 65 str \src, [\temp_reg, \mem2] 66 .endm 67#else 68 // .equ PSHIFT , 1 69 #define PSHIFT 1 70 .macro PLOAD dest:req, mem:req 71 ldrh \dest, [\mem] 72 .endm 73 .macro PLOAD_PREINDEXED dest:req, mem:req, offset:req 74 ldrh \dest, [\mem, \offset]! 75 .endm 76 .macro PLOAD_2 dest:req, mem1:req, mem2:req 77 ldrh \dest, [\mem1, \mem2] 78 .endm 79 .macro PLOAD_LSL dest:req, mem1:req, mem2:req 80 ldrh \dest, [\mem1, \mem2, lsl #PSHIFT] 81 .endm 82 .macro PSTORE src:req, mem:req 83 strh \src, [\mem] 84 .endm 85 .macro PSTORE_2 src:req, mem1:req, mem2:req 86 strh \src, [\mem1, \mem2] 87 .endm 88 .macro PSTORE_LSL src:req, mem1:req, mem2:req 89 strh \src, [\mem1, \mem2, lsl #PSHIFT] 90 .endm 91 .macro PSTORE_LSL_M1 src:req, mem1:req, mem2:req, temp_reg:req 92 strh \src, [\mem1, \mem2] 93 .endm 94#endif 95 96.equ PMULT , (1 << PSHIFT) 97.equ PMULT_2 , (2 << PSHIFT) 98 99.equ kMatchSpecLen_Error_Data , (1 << 9) 100 101# x7 t0 : NORM_CALC : prob2 (IF_BIT_1) 102# x6 t1 : NORM_CALC : probs_state 103# x8 t2 : (LITM) temp : (TREE) temp 104# x4 t3 : (LITM) bit : (TREE) temp : UPDATE_0/UPDATE_0 temp 105# x10 t4 : (LITM) offs : (TREE) probs_PMULT : numBits 106# x9 t5 : (LITM) match : sym2 (ShortDist) 107# x1 t6 : (LITM) litm_prob : (TREE) prob_reg : pbPos 108# x2 t7 : (LITM) prm : probBranch : cnt 109# x3 sym : dist 110# x12 len 111# x0 range 112# x5 cod 113 114 115#define range w0 116 117// t6 118#define pbPos w1 119#define pbPos_R r1 120#define prob_reg w1 121#define litm_prob prob_reg 122 123// t7 124#define probBranch w2 125#define cnt w2 126#define cnt_R r2 127#define prm r2 128 129#define sym w3 130#define sym_R r3 131#define dist sym 132 133#define t3 w4 134#define bit w4 135#define bit_R r4 136#define update_temp_reg r4 137 138#define cod w5 139 140#define t1 w6 141#define t1_R r6 142#define probs_state t1_R 143 144#define t0 w7 145#define t0_R r7 146#define prob2 t0 147 148#define t2 w8 149#define t2_R r8 150 151// t5 152#define match w9 153#define sym2 w9 154#define sym2_R r9 155 156#define t4 w10 157#define t4_R r10 158 159#define offs w10 160#define offs_R r10 161 162#define probs r11 163 164#define len w12 165#define len_R x12 166 167#define state w13 168#define state_R r13 169 170#define dicPos r14 171#define buf r15 172#define bufLimit r16 173#define dicBufSize r17 174 175#define limit r19 176#define rep0 w20 177#define rep0_R r20 178#define rep1 w21 179#define rep2 w22 180#define rep3 w23 181#define dic r24 182#define probs_IsMatch r25 183#define probs_Spec r26 184#define checkDicSize w27 185#define processedPos w28 186#define pbMask w29 187#define lc2_lpMask w30 188 189 190.equ kNumBitModelTotalBits , 11 191.equ kBitModelTotal , (1 << kNumBitModelTotalBits) 192.equ kNumMoveBits , 5 193.equ kBitModelOffset , (kBitModelTotal - (1 << kNumMoveBits) + 1) 194 195.macro NORM_2 macro 196 ldrb t0, [buf], 1 197 shl range, 8 198 orr cod, t0, cod, lsl 8 199 /* 200 mov t0, cod 201 ldrb cod, [buf], 1 202 shl range, 8 203 bfi cod, t0, #8, #24 204 */ 205.endm 206 207.macro TEST_HIGH_BYTE_range macro 208 tst range, 0xFF000000 209.endm 210 211.macro NORM macro 212 TEST_HIGH_BYTE_range 213 jnz 1f 214 NORM_2 2151: 216.endm 217 218 219# ---------- Branch MACROS ---------- 220 221.macro UPDATE_0__0 222 sub prob2, probBranch, kBitModelOffset 223.endm 224 225.macro UPDATE_0__1 226 sub probBranch, probBranch, prob2, asr #(kNumMoveBits) 227.endm 228 229.macro UPDATE_0__2 probsArray:req, probOffset:req, probDisp:req 230 .if \probDisp == 0 231 PSTORE_2 probBranch, \probsArray, \probOffset 232 .elseif \probOffset == 0 233 PSTORE_2 probBranch, \probsArray, \probDisp * PMULT 234 .else 235 .error "unsupported" 236 // add update_temp_reg, \probsArray, \probOffset 237 PSTORE_2 probBranch, update_temp_reg, \probDisp * PMULT 238 .endif 239.endm 240 241.macro UPDATE_0 probsArray:req, probOffset:req, probDisp:req 242 UPDATE_0__0 243 UPDATE_0__1 244 UPDATE_0__2 \probsArray, \probOffset, \probDisp 245.endm 246 247 248.macro UPDATE_1 probsArray:req, probOffset:req, probDisp:req 249 // sub cod, cod, prob2 250 // sub range, range, prob2 251 p2_sub cod, range 252 sub range, prob2, range 253 sub prob2, probBranch, probBranch, lsr #(kNumMoveBits) 254 .if \probDisp == 0 255 PSTORE_2 prob2, \probsArray, \probOffset 256 .elseif \probOffset == 0 257 PSTORE_2 prob2, \probsArray, \probDisp * PMULT 258 .else 259 .error "unsupported" 260 // add update_temp_reg, \probsArray, \probOffset 261 PSTORE_2 prob2, update_temp_reg, \probDisp * PMULT 262 .endif 263.endm 264 265 266.macro CMP_COD_BASE 267 NORM 268 // lsr prob2, range, kNumBitModelTotalBits 269 // imul prob2, probBranch 270 // cmp cod, prob2 271 mov prob2, range 272 shr range, kNumBitModelTotalBits 273 imul range, probBranch 274 cmp cod, range 275.endm 276 277.macro CMP_COD_1 probsArray:req 278 PLOAD probBranch, \probsArray 279 CMP_COD_BASE 280.endm 281 282.macro CMP_COD_3 probsArray:req, probOffset:req, probDisp:req 283 .if \probDisp == 0 284 PLOAD_2 probBranch, \probsArray, \probOffset 285 .elseif \probOffset == 0 286 PLOAD_2 probBranch, \probsArray, \probDisp * PMULT 287 .else 288 .error "unsupported" 289 add update_temp_reg, \probsArray, \probOffset 290 PLOAD_2 probBranch, update_temp_reg, \probDisp * PMULT 291 .endif 292 CMP_COD_BASE 293.endm 294 295 296.macro IF_BIT_1_NOUP probsArray:req, probOffset:req, probDisp:req, toLabel:req 297 CMP_COD_3 \probsArray, \probOffset, \probDisp 298 jae \toLabel 299.endm 300 301 302.macro IF_BIT_1 probsArray:req, probOffset:req, probDisp:req, toLabel:req 303 IF_BIT_1_NOUP \probsArray, \probOffset, \probDisp, \toLabel 304 UPDATE_0 \probsArray, \probOffset, \probDisp 305.endm 306 307 308.macro IF_BIT_0_NOUP probsArray:req, probOffset:req, probDisp:req, toLabel:req 309 CMP_COD_3 \probsArray, \probOffset, \probDisp 310 jb \toLabel 311.endm 312 313.macro IF_BIT_0_NOUP_1 probsArray:req, toLabel:req 314 CMP_COD_1 \probsArray 315 jb \toLabel 316.endm 317 318 319# ---------- CMOV MACROS ---------- 320 321.macro NORM_LSR 322 NORM 323 lsr t0, range, #kNumBitModelTotalBits 324.endm 325 326.macro COD_RANGE_SUB 327 subs t1, cod, t0 328 p2_sub range, t0 329.endm 330 331.macro RANGE_IMUL prob:req 332 imul t0, \prob 333.endm 334 335.macro NORM_CALC prob:req 336 NORM_LSR 337 RANGE_IMUL \prob 338 COD_RANGE_SUB 339.endm 340 341.macro CMOV_range 342 cmovb range, t0 343.endm 344 345.macro CMOV_code 346 cmovae cod, t1 347.endm 348 349.macro CMOV_code_Model_Pre prob:req 350 sub t0, \prob, kBitModelOffset 351 CMOV_code 352 cmovae t0, \prob 353.endm 354 355 356.macro PUP_BASE_2 prob:req, dest_reg:req 357 # only sar works for both 16/32 bit prob modes 358 sub \dest_reg, \prob, \dest_reg, asr #(kNumMoveBits) 359.endm 360 361.macro PUP prob:req, probPtr:req, mem2:req 362 PUP_BASE_2 \prob, t0 363 PSTORE_2 t0, \probPtr, \mem2 364.endm 365 366 367 368#define probs_PMULT t4_R 369 370.macro BIT_01 371 add probs_PMULT, probs, PMULT 372.endm 373 374 375.macro BIT_0_R prob:req 376 PLOAD_2 \prob, probs, 1 * PMULT 377 NORM_LSR 378 sub t3, \prob, kBitModelOffset 379 RANGE_IMUL \prob 380 PLOAD_2 t2, probs, 1 * PMULT_2 381 COD_RANGE_SUB 382 CMOV_range 383 cmovae t3, \prob 384 PLOAD_2 t0, probs, 1 * PMULT_2 + PMULT 385 PUP_BASE_2 \prob, t3 386 csel \prob, t2, t0, lo 387 CMOV_code 388 mov sym, 2 389 PSTORE_2 t3, probs, 1 * PMULT 390 adc sym, sym, wzr 391 BIT_01 392.endm 393 394.macro BIT_1_R prob:req 395 NORM_LSR 396 p2_add sym, sym 397 sub t3, \prob, kBitModelOffset 398 RANGE_IMUL \prob 399 PLOAD_LSL t2, probs, sym_R 400 COD_RANGE_SUB 401 CMOV_range 402 cmovae t3, \prob 403 PLOAD_LSL t0, probs_PMULT, sym_R 404 PUP_BASE_2 \prob, t3 405 csel \prob, t2, t0, lo 406 CMOV_code 407 PSTORE_LSL_M1 t3, probs, sym_R, t2_R 408 adc sym, sym, wzr 409.endm 410 411 412.macro BIT_2_R prob:req 413 NORM_LSR 414 p2_add sym, sym 415 sub t3, \prob, kBitModelOffset 416 RANGE_IMUL \prob 417 COD_RANGE_SUB 418 CMOV_range 419 cmovae t3, \prob 420 CMOV_code 421 PUP_BASE_2 \prob, t3 422 PSTORE_LSL_M1 t3, probs, sym_R, t2_R 423 adc sym, sym, wzr 424.endm 425 426 427# ---------- MATCHED LITERAL ---------- 428 429.macro LITM_0 macro 430 shl match, (PSHIFT + 1) 431 and bit, match, 256 * PMULT 432 add prm, probs, 256 * PMULT + 1 * PMULT 433 p2_add match, match 434 p2_add prm, bit_R 435 eor offs, bit, 256 * PMULT 436 PLOAD litm_prob, prm 437 438 NORM_LSR 439 sub t2, litm_prob, kBitModelOffset 440 RANGE_IMUL litm_prob 441 COD_RANGE_SUB 442 cmovae offs, bit 443 CMOV_range 444 and bit, match, offs 445 cmovae t2, litm_prob 446 CMOV_code 447 mov sym, 2 448 PUP_BASE_2 litm_prob, t2 449 PSTORE t2, prm 450 add prm, probs, offs_R 451 adc sym, sym, wzr 452.endm 453 454.macro LITM macro 455 p2_add prm, bit_R 456 xor offs, bit 457 PLOAD_LSL litm_prob, prm, sym_R 458 459 NORM_LSR 460 p2_add match, match 461 sub t2, litm_prob, kBitModelOffset 462 RANGE_IMUL litm_prob 463 COD_RANGE_SUB 464 cmovae offs, bit 465 CMOV_range 466 and bit, match, offs 467 cmovae t2, litm_prob 468 CMOV_code 469 PUP_BASE_2 litm_prob, t2 470 PSTORE_LSL t2, prm, sym_R 471 add prm, probs, offs_R 472 adc sym, sym, sym 473.endm 474 475 476.macro LITM_2 macro 477 p2_add prm, bit_R 478 PLOAD_LSL litm_prob, prm, sym_R 479 480 NORM_LSR 481 sub t2, litm_prob, kBitModelOffset 482 RANGE_IMUL litm_prob 483 COD_RANGE_SUB 484 CMOV_range 485 cmovae t2, litm_prob 486 CMOV_code 487 PUP_BASE_2 litm_prob, t2 488 PSTORE_LSL t2, prm, sym_R 489 adc sym, sym, sym 490.endm 491 492 493# ---------- REVERSE BITS ---------- 494 495.macro REV_0 prob:req 496 NORM_CALC \prob 497 CMOV_range 498 PLOAD t2, sym2_R 499 PLOAD_2 t3, probs, 3 * PMULT 500 CMOV_code_Model_Pre \prob 501 add t1_R, probs, 3 * PMULT 502 cmovae sym2_R, t1_R 503 PUP \prob, probs, 1 * PMULT 504 csel \prob, t2, t3, lo 505.endm 506 507 508.macro REV_1 prob:req, step:req 509 NORM_LSR 510 PLOAD_PREINDEXED t2, sym2_R, (\step * PMULT) 511 RANGE_IMUL \prob 512 COD_RANGE_SUB 513 CMOV_range 514 PLOAD_2 t3, sym2_R, (\step * PMULT) 515 sub t0, \prob, kBitModelOffset 516 CMOV_code 517 add t1_R, sym2_R, \step * PMULT 518 cmovae t0, \prob 519 cmovae sym2_R, t1_R 520 PUP_BASE_2 \prob, t0 521 csel \prob, t2, t3, lo 522 PSTORE_2 t0, t1_R, 0 - \step * PMULT_2 523.endm 524 525 526.macro REV_2 prob:req, step:req 527 sub t1_R, sym2_R, probs 528 NORM_LSR 529 orr sym, sym, t1, lsr #PSHIFT 530 RANGE_IMUL \prob 531 COD_RANGE_SUB 532 sub t2, sym, \step 533 CMOV_range 534 cmovb sym, t2 535 CMOV_code_Model_Pre \prob 536 PUP \prob, sym2_R, 0 537.endm 538 539 540.macro REV_1_VAR prob:req 541 PLOAD \prob, sym_R 542 mov probs, sym_R 543 p2_add sym_R, sym2_R 544 NORM_LSR 545 add t2_R, sym_R, sym2_R 546 RANGE_IMUL \prob 547 COD_RANGE_SUB 548 cmovae sym_R, t2_R 549 CMOV_range 550 CMOV_code_Model_Pre \prob 551 p2_add sym2, sym2 552 PUP \prob, probs, 0 553.endm 554 555 556.macro add_big dest:req, src:req, param:req 557 .if (\param) < (1 << 12) 558 add \dest, \src, \param 559 .else 560 #ifndef _LZMA_PROB32 561 .error "unexpcted add_big expansion" 562 #endif 563 add \dest, \src, (\param) / 2 564 add \dest, \dest, (\param) - (\param) / 2 565 .endif 566.endm 567 568.macro sub_big dest:req, src:req, param:req 569 .if (\param) < (1 << 12) 570 sub \dest, \src, \param 571 .else 572 #ifndef _LZMA_PROB32 573 .error "unexpcted sub_big expansion" 574 #endif 575 sub \dest, \src, (\param) / 2 576 sub \dest, \dest, (\param) - (\param) / 2 577 .endif 578.endm 579 580 581.macro SET_probs offset:req 582 // add_big probs, probs_Spec, (\offset) * PMULT 583 add probs, probs_IsMatch, ((\offset) - IsMatch) * PMULT 584.endm 585 586 587.macro LIT_PROBS 588 add sym, sym, processedPos, lsl 8 589 inc processedPos 590 UPDATE_0__0 591 shl sym, lc2_lpMask 592 SET_probs Literal 593 p2_and sym, lc2_lpMask 594 // p2_add probs_state, pbPos_R 595 p2_add probs, sym_R 596 UPDATE_0__1 597 add probs, probs, sym_R, lsl 1 598 UPDATE_0__2 probs_state, pbPos_R, 0 599.endm 600 601 602 603.equ kNumPosBitsMax , 4 604.equ kNumPosStatesMax , (1 << kNumPosBitsMax) 605 606.equ kLenNumLowBits , 3 607.equ kLenNumLowSymbols , (1 << kLenNumLowBits) 608.equ kLenNumHighBits , 8 609.equ kLenNumHighSymbols , (1 << kLenNumHighBits) 610.equ kNumLenProbs , (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols) 611 612.equ LenLow , 0 613.equ LenChoice , LenLow 614.equ LenChoice2 , (LenLow + kLenNumLowSymbols) 615.equ LenHigh , (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax) 616 617.equ kNumStates , 12 618.equ kNumStates2 , 16 619.equ kNumLitStates , 7 620 621.equ kStartPosModelIndex , 4 622.equ kEndPosModelIndex , 14 623.equ kNumFullDistances , (1 << (kEndPosModelIndex >> 1)) 624 625.equ kNumPosSlotBits , 6 626.equ kNumLenToPosStates , 4 627 628.equ kNumAlignBits , 4 629.equ kAlignTableSize , (1 << kNumAlignBits) 630 631.equ kMatchMinLen , 2 632.equ kMatchSpecLenStart , (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) 633 634// .equ kStartOffset , 1408 635.equ kStartOffset , 0 636.equ SpecPos , (-kStartOffset) 637.equ IsRep0Long , (SpecPos + kNumFullDistances) 638.equ RepLenCoder , (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) 639.equ LenCoder , (RepLenCoder + kNumLenProbs) 640.equ IsMatch , (LenCoder + kNumLenProbs) 641.equ kAlign , (IsMatch + (kNumStates2 << kNumPosBitsMax)) 642.equ IsRep , (kAlign + kAlignTableSize) 643.equ IsRepG0 , (IsRep + kNumStates) 644.equ IsRepG1 , (IsRepG0 + kNumStates) 645.equ IsRepG2 , (IsRepG1 + kNumStates) 646.equ PosSlot , (IsRepG2 + kNumStates) 647.equ Literal , (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) 648.equ NUM_BASE_PROBS , (Literal + kStartOffset) 649 650.if kStartOffset != 0 // && IsMatch != 0 651 .error "Stop_Compiling_Bad_StartOffset" 652.endif 653 654.if NUM_BASE_PROBS != 1984 655 .error "Stop_Compiling_Bad_LZMA_PROBS" 656.endif 657 658.equ offset_lc , 0 659.equ offset_lp , 1 660.equ offset_pb , 2 661.equ offset_dicSize , 4 662.equ offset_probs , 4 + offset_dicSize 663.equ offset_probs_1664 , 8 + offset_probs 664.equ offset_dic , 8 + offset_probs_1664 665.equ offset_dicBufSize , 8 + offset_dic 666.equ offset_dicPos , 8 + offset_dicBufSize 667.equ offset_buf , 8 + offset_dicPos 668.equ offset_range , 8 + offset_buf 669.equ offset_code , 4 + offset_range 670.equ offset_processedPos , 4 + offset_code 671.equ offset_checkDicSize , 4 + offset_processedPos 672.equ offset_rep0 , 4 + offset_checkDicSize 673.equ offset_rep1 , 4 + offset_rep0 674.equ offset_rep2 , 4 + offset_rep1 675.equ offset_rep3 , 4 + offset_rep2 676.equ offset_state , 4 + offset_rep3 677.equ offset_remainLen , 4 + offset_state 678.equ offset_TOTAL_SIZE , 4 + offset_remainLen 679 680.if offset_TOTAL_SIZE != 96 681 .error "Incorrect offset_TOTAL_SIZE" 682.endif 683 684 685.macro IsMatchBranch_Pre 686 # prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; 687 and pbPos, pbMask, processedPos, lsl #(kLenNumLowBits + 1 + PSHIFT) 688 add probs_state, probs_IsMatch, state_R 689.endm 690 691 692/* 693.macro IsMatchBranch 694 IsMatchBranch_Pre 695 IF_BIT_1 probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label 696.endm 697*/ 698 699.macro CheckLimits 700 cmp buf, bufLimit 701 jae fin_OK 702 cmp dicPos, limit 703 jae fin_OK 704.endm 705 706#define CheckLimits_lit CheckLimits 707/* 708.macro CheckLimits_lit 709 cmp buf, bufLimit 710 jae fin_OK_lit 711 cmp dicPos, limit 712 jae fin_OK_lit 713.endm 714*/ 715 716 717#define PARAM_lzma REG_ABI_PARAM_0 718#define PARAM_limit REG_ABI_PARAM_1 719#define PARAM_bufLimit REG_ABI_PARAM_2 720 721 722.macro LOAD_LZMA_VAR reg:req, struct_offs:req 723 ldr \reg, [PARAM_lzma, \struct_offs] 724.endm 725 726.macro LOAD_LZMA_BYTE reg:req, struct_offs:req 727 ldrb \reg, [PARAM_lzma, \struct_offs] 728.endm 729 730.macro LOAD_LZMA_PAIR reg0:req, reg1:req, struct_offs:req 731 ldp \reg0, \reg1, [PARAM_lzma, \struct_offs] 732.endm 733 734 735LzmaDec_DecodeReal_3: 736_LzmaDec_DecodeReal_3: 737/* 738.LFB0: 739 .cfi_startproc 740*/ 741 742 stp x19, x20, [sp, -128]! 743 stp x21, x22, [sp, 16] 744 stp x23, x24, [sp, 32] 745 stp x25, x26, [sp, 48] 746 stp x27, x28, [sp, 64] 747 stp x29, x30, [sp, 80] 748 749 str PARAM_lzma, [sp, 120] 750 751 mov bufLimit, PARAM_bufLimit 752 mov limit, PARAM_limit 753 754 LOAD_LZMA_PAIR dic, dicBufSize, offset_dic 755 LOAD_LZMA_PAIR dicPos, buf, offset_dicPos 756 LOAD_LZMA_PAIR rep0, rep1, offset_rep0 757 LOAD_LZMA_PAIR rep2, rep3, offset_rep2 758 759 mov t0, 1 << (kLenNumLowBits + 1 + PSHIFT) 760 LOAD_LZMA_BYTE pbMask, offset_pb 761 p2_add limit, dic 762 mov len, wzr // we can set it in all requiread branches instead 763 lsl pbMask, t0, pbMask 764 p2_add dicPos, dic 765 p2_sub pbMask, t0 766 767 LOAD_LZMA_BYTE lc2_lpMask, offset_lc 768 mov t0, 256 << PSHIFT 769 LOAD_LZMA_BYTE t1, offset_lp 770 p2_add t1, lc2_lpMask 771 p2_sub lc2_lpMask, (256 << PSHIFT) - PSHIFT 772 shl t0, t1 773 p2_add lc2_lpMask, t0 774 775 LOAD_LZMA_VAR probs_Spec, offset_probs 776 LOAD_LZMA_VAR checkDicSize, offset_checkDicSize 777 LOAD_LZMA_VAR processedPos, offset_processedPos 778 LOAD_LZMA_VAR state, offset_state 779 // range is r0 : this load must be last don't move 780 LOAD_LZMA_PAIR range, cod, offset_range 781 mov sym, wzr 782 shl state, PSHIFT 783 784 add_big probs_IsMatch, probs_Spec, ((IsMatch - SpecPos) << PSHIFT) 785 786 // if (processedPos != 0 || checkDicSize != 0) 787 orr t0, checkDicSize, processedPos 788 cbz t0, 1f 789 add t0_R, dicBufSize, dic 790 cmp dicPos, dic 791 cmovne t0_R, dicPos 792 ldrb sym, [t0_R, -1] 7931: 794 IsMatchBranch_Pre 795 cmp state, 4 * PMULT 796 jb lit_end 797 cmp state, kNumLitStates * PMULT 798 jb lit_matched_end 799 jmp lz_end 800 801 802 803#define BIT_0 BIT_0_R prob_reg 804#define BIT_1 BIT_1_R prob_reg 805#define BIT_2 BIT_2_R prob_reg 806 807# ---------- LITERAL ---------- 808MY_ALIGN_64 809lit_start: 810 mov state, wzr 811lit_start_2: 812 LIT_PROBS 813 814 #ifdef _LZMA_SIZE_OPT 815 816 PLOAD_2 prob_reg, probs, 1 * PMULT 817 mov sym, 1 818 BIT_01 819MY_ALIGN_FOR_LOOP 820lit_loop: 821 BIT_1 822 tbz sym, 7, lit_loop 823 824 #else 825 826 BIT_0 827 BIT_1 828 BIT_1 829 BIT_1 830 BIT_1 831 BIT_1 832 BIT_1 833 834 #endif 835 836 BIT_2 837 IsMatchBranch_Pre 838 strb sym, [dicPos], 1 839 p2_and sym, 255 840 841 CheckLimits_lit 842lit_end: 843 IF_BIT_0_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), lit_start 844 845 # jmp IsMatch_label 846 847 848#define FLAG_STATE_BITS (4 + PSHIFT) 849 850# ---------- MATCHES ---------- 851# MY_ALIGN_FOR_ENTRY 852IsMatch_label: 853 UPDATE_1 probs_state, pbPos_R, (IsMatch - IsMatch) 854 IF_BIT_1 probs_state, 0, (IsRep - IsMatch), IsRep_label 855 856 SET_probs LenCoder 857 or state, (1 << FLAG_STATE_BITS) 858 859# ---------- LEN DECODE ---------- 860len_decode: 861 mov len, 8 - kMatchMinLen 862 IF_BIT_0_NOUP_1 probs, len_mid_0 863 UPDATE_1 probs, 0, 0 864 p2_add probs, (1 << (kLenNumLowBits + PSHIFT)) 865 mov len, 0 - kMatchMinLen 866 IF_BIT_0_NOUP_1 probs, len_mid_0 867 UPDATE_1 probs, 0, 0 868 p2_add probs, LenHigh * PMULT - (1 << (kLenNumLowBits + PSHIFT)) 869 870 #if 0 == 1 871 BIT_0 872 BIT_1 873 BIT_1 874 BIT_1 875 BIT_1 876 BIT_1 877 #else 878 PLOAD_2 prob_reg, probs, 1 * PMULT 879 mov sym, 1 880 BIT_01 881MY_ALIGN_FOR_LOOP 882len8_loop: 883 BIT_1 884 tbz sym, 6, len8_loop 885 #endif 886 887 mov len, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - kMatchMinLen 888 jmp len_mid_2 889 890MY_ALIGN_FOR_ENTRY 891len_mid_0: 892 UPDATE_0 probs, 0, 0 893 p2_add probs, pbPos_R 894 BIT_0 895len_mid_2: 896 BIT_1 897 BIT_2 898 sub len, sym, len 899 tbz state, FLAG_STATE_BITS, copy_match 900 901# ---------- DECODE DISTANCE ---------- 902 // probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); 903 904 mov t0, 3 + kMatchMinLen 905 cmp len, 3 + kMatchMinLen 906 cmovb t0, len 907 SET_probs PosSlot - (kMatchMinLen << (kNumPosSlotBits)) 908 add probs, probs, t0_R, lsl #(kNumPosSlotBits + PSHIFT) 909 910 #ifdef _LZMA_SIZE_OPT 911 912 PLOAD_2 prob_reg, probs, 1 * PMULT 913 mov sym, 1 914 BIT_01 915MY_ALIGN_FOR_LOOP 916slot_loop: 917 BIT_1 918 tbz sym, 5, slot_loop 919 920 #else 921 922 BIT_0 923 BIT_1 924 BIT_1 925 BIT_1 926 BIT_1 927 928 #endif 929 930 #define numBits t4 931 mov numBits, sym 932 BIT_2 933 // we need only low bits 934 p2_and sym, 3 935 cmp numBits, 32 + kEndPosModelIndex / 2 936 jb short_dist 937 938 SET_probs kAlign 939 940 # unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); 941 p2_sub numBits, (32 + 1 + kNumAlignBits) 942 # distance = (2 | (distance & 1)); 943 or sym, 2 944 PLOAD_2 prob_reg, probs, 1 * PMULT 945 add sym2_R, probs, 2 * PMULT 946 947# ---------- DIRECT DISTANCE ---------- 948 949.macro DIRECT_1 950 shr range, 1 951 subs t0, cod, range 952 p2_add sym, sym 953 // add t1, sym, 1 954 csel cod, cod, t0, mi 955 csinc sym, sym, sym, mi 956 // csel sym, t1, sym, pl 957 // adc sym, sym, sym // not 100% compatible for "corruptued-allowed" LZMA streams 958 dec_s numBits 959 je direct_end 960.endm 961 962 #ifdef _LZMA_SIZE_OPT 963 964 jmp direct_norm 965MY_ALIGN_FOR_ENTRY 966direct_loop: 967 DIRECT_1 968direct_norm: 969 TEST_HIGH_BYTE_range 970 jnz direct_loop 971 NORM_2 972 jmp direct_loop 973 974 #else 975 976.macro DIRECT_2 977 TEST_HIGH_BYTE_range 978 jz direct_unroll 979 DIRECT_1 980.endm 981 982 DIRECT_2 983 DIRECT_2 984 DIRECT_2 985 DIRECT_2 986 DIRECT_2 987 DIRECT_2 988 DIRECT_2 989 DIRECT_2 990 991direct_unroll: 992 NORM_2 993 DIRECT_1 994 DIRECT_1 995 DIRECT_1 996 DIRECT_1 997 DIRECT_1 998 DIRECT_1 999 DIRECT_1 1000 DIRECT_1 1001 jmp direct_unroll 1002 1003 #endif 1004 1005MY_ALIGN_FOR_ENTRY 1006direct_end: 1007 shl sym, kNumAlignBits 1008 REV_0 prob_reg 1009 REV_1 prob_reg, 2 1010 REV_1 prob_reg, 4 1011 REV_2 prob_reg, 8 1012 1013decode_dist_end: 1014 1015 // if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) 1016 1017 tst checkDicSize, checkDicSize 1018 csel t0, processedPos, checkDicSize, eq 1019 cmp sym, t0 1020 jae end_of_payload 1021 // jmp end_of_payload # for debug 1022 1023 mov rep3, rep2 1024 mov rep2, rep1 1025 mov rep1, rep0 1026 add rep0, sym, 1 1027 1028.macro STATE_UPDATE_FOR_MATCH 1029 // state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; 1030 // cmp state, (kNumStates + kNumLitStates) * PMULT 1031 cmp state, kNumLitStates * PMULT + (1 << FLAG_STATE_BITS) 1032 mov state, kNumLitStates * PMULT 1033 mov t0, (kNumLitStates + 3) * PMULT 1034 cmovae state, t0 1035.endm 1036 STATE_UPDATE_FOR_MATCH 1037 1038# ---------- COPY MATCH ---------- 1039copy_match: 1040 1041 // if ((rem = limit - dicPos) == 0) break // return SZ_ERROR_DATA; 1042 subs cnt_R, limit, dicPos 1043 // jz fin_dicPos_LIMIT 1044 jz fin_OK 1045 1046 // curLen = ((rem < len) ? (unsigned)rem : len); 1047 cmp cnt_R, len_R 1048 cmovae cnt, len 1049 1050 sub t0_R, dicPos, dic 1051 p2_add dicPos, cnt_R 1052 p2_add processedPos, cnt 1053 p2_sub len, cnt 1054 1055 // pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); 1056 p2_sub_s t0_R, rep0_R 1057 jae 1f 1058 1059 cmn t0_R, cnt_R 1060 p2_add t0_R, dicBufSize 1061 ja copy_match_cross 10621: 1063# ---------- COPY MATCH FAST ---------- 1064 # t0_R : src_pos 1065 p2_add t0_R, dic 1066 ldrb sym, [t0_R] 1067 p2_add t0_R, cnt_R 1068 p1_neg cnt_R 1069 1070copy_common: 1071 dec dicPos 1072 1073 # dicPos : (ptr_to_last_dest_BYTE) 1074 # t0_R : (src_lim) 1075 # cnt_R : (-curLen) 1076 1077 IsMatchBranch_Pre 1078 1079 inc_s cnt_R 1080 jz copy_end 1081 1082 cmp rep0, 1 1083 je copy_match_0 1084 1085 #ifdef LZMA_USE_2BYTES_COPY 1086 strb sym, [dicPos, cnt_R] 1087 dec dicPos 1088 # dicPos : (ptr_to_last_dest_16bitWORD) 1089 p2_and cnt_R, -2 1090 ldrh sym, [t0_R, cnt_R] 1091 adds cnt_R, cnt_R, 2 1092 jz 2f 1093MY_ALIGN_FOR_LOOP 10941: 1095 /* 1096 strh sym, [dicPos, cnt_R] 1097 ldrh sym, [t0_R, cnt_R] 1098 adds cnt_R, cnt_R, 2 1099 jz 2f 1100 */ 1101 1102 strh sym, [dicPos, cnt_R] 1103 ldrh sym, [t0_R, cnt_R] 1104 adds cnt_R, cnt_R, 2 1105 jnz 1b 11062: 1107 1108 /* 1109 // for universal little/big endian code, but slow 1110 strh sym, [dicPos] 1111 inc dicPos 1112 ldrb sym, [t0_R, -1] 1113 */ 1114 1115 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 1116 // we must improve big-endian detection for another compilers 1117 // for big-endian we need to revert bytes 1118 rev16 sym, sym 1119 #endif 1120 1121 // (sym) must represent as little-endian here: 1122 strb sym, [dicPos], 1 1123 shr sym, 8 1124 1125 #else 1126 1127MY_ALIGN_FOR_LOOP 11281: 1129 strb sym, [dicPos, cnt_R] 1130 ldrb sym, [t0_R, cnt_R] 1131 inc_s cnt_R 1132 jz copy_end 1133 1134 strb sym, [dicPos, cnt_R] 1135 ldrb sym, [t0_R, cnt_R] 1136 inc_s cnt_R 1137 jnz 1b 1138 #endif 1139 1140copy_end: 1141lz_end_match: 1142 strb sym, [dicPos], 1 1143 1144 # IsMatchBranch_Pre 1145 CheckLimits 1146lz_end: 1147 IF_BIT_1_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label 1148 1149 1150 1151# ---------- LITERAL MATCHED ---------- 1152 1153 LIT_PROBS 1154 1155 // matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; 1156 1157 sub t0_R, dicPos, dic 1158 p2_sub_s t0_R, rep0_R 1159 1160 #ifdef LZMA_USE_CMOV_LZ_WRAP 1161 add t1_R, t0_R, dicBufSize 1162 cmovb t0_R, t1_R 1163 #else 1164 jae 1f 1165 p2_add t0_R, dicBufSize 11661: 1167 #endif 1168 1169 ldrb match, [dic, t0_R] 1170 1171 // state -= (state < 10) ? 3 : 6; 1172 sub sym, state, 6 * PMULT 1173 cmp state, 10 * PMULT 1174 p2_sub state, 3 * PMULT 1175 cmovae state, sym 1176 1177 #ifdef _LZMA_SIZE_OPT 1178 1179 mov offs, 256 * PMULT 1180 shl match, (PSHIFT + 1) 1181 mov sym, 1 1182 and bit, match, offs 1183 add prm, probs, offs_R 1184 1185MY_ALIGN_FOR_LOOP 1186litm_loop: 1187 LITM 1188 tbz sym, 8, litm_loop 1189 1190 #else 1191 1192 LITM_0 1193 LITM 1194 LITM 1195 LITM 1196 LITM 1197 LITM 1198 LITM 1199 LITM_2 1200 1201 #endif 1202 1203 IsMatchBranch_Pre 1204 strb sym, [dicPos], 1 1205 p2_and sym, 255 1206 1207 // mov len, wzr // LITM uses same regisetr (len / offs). So we clear it 1208 CheckLimits_lit 1209lit_matched_end: 1210 IF_BIT_1_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label 1211 # IsMatchBranch 1212 p2_sub state, 3 * PMULT 1213 jmp lit_start_2 1214 1215 1216 1217# ---------- REP 0 LITERAL ---------- 1218MY_ALIGN_FOR_ENTRY 1219IsRep0Short_label: 1220 UPDATE_0 probs_state, pbPos_R, 0 1221 1222 // dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; 1223 sub t0_R, dicPos, dic 1224 1225 // state = state < kNumLitStates ? 9 : 11; 1226 or state, 1 * PMULT 1227 1228 # the caller doesn't allow (dicPos >= limit) case for REP_SHORT 1229 # so we don't need the following (dicPos == limit) check here: 1230 # cmp dicPos, limit 1231 # jae fin_dicPos_LIMIT_REP_SHORT 1232 # // jmp fin_dicPos_LIMIT_REP_SHORT // for testing/debug puposes 1233 1234 inc processedPos 1235 1236 IsMatchBranch_Pre 1237 1238 p2_sub_s t0_R, rep0_R 1239 #ifdef LZMA_USE_CMOV_LZ_WRAP 1240 add sym_R, t0_R, dicBufSize 1241 cmovb t0_R, sym_R 1242 #else 1243 jae 1f 1244 p2_add t0_R, dicBufSize 12451: 1246 #endif 1247 1248 ldrb sym, [dic, t0_R] 1249 // mov len, wzr 1250 jmp lz_end_match 1251 1252MY_ALIGN_FOR_ENTRY 1253IsRep_label: 1254 UPDATE_1 probs_state, 0, (IsRep - IsMatch) 1255 1256 # The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode. 1257 # So we don't check it here. 1258 1259 # mov t0, processedPos 1260 # or t0, checkDicSize 1261 # jz fin_ERROR_2 1262 1263 // state = state < kNumLitStates ? 8 : 11; 1264 cmp state, kNumLitStates * PMULT 1265 mov state, 8 * PMULT 1266 mov probBranch, 11 * PMULT 1267 cmovae state, probBranch 1268 1269 SET_probs RepLenCoder 1270 1271 IF_BIT_1 probs_state, 0, (IsRepG0 - IsMatch), IsRepG0_label 1272 sub_big probs_state, probs_state, (IsMatch - IsRep0Long) << PSHIFT 1273 IF_BIT_0_NOUP probs_state, pbPos_R, 0, IsRep0Short_label 1274 UPDATE_1 probs_state, pbPos_R, 0 1275 jmp len_decode 1276 1277MY_ALIGN_FOR_ENTRY 1278IsRepG0_label: 1279 UPDATE_1 probs_state, 0, (IsRepG0 - IsMatch) 1280 IF_BIT_1 probs_state, 0, (IsRepG1 - IsMatch), IsRepG1_label 1281 mov dist, rep1 1282 mov rep1, rep0 1283 mov rep0, dist 1284 jmp len_decode 1285 1286# MY_ALIGN_FOR_ENTRY 1287IsRepG1_label: 1288 UPDATE_1 probs_state, 0, (IsRepG1 - IsMatch) 1289 IF_BIT_1 probs_state, 0, (IsRepG2 - IsMatch), IsRepG2_label 1290 mov dist, rep2 1291 mov rep2, rep1 1292 mov rep1, rep0 1293 mov rep0, dist 1294 jmp len_decode 1295 1296# MY_ALIGN_FOR_ENTRY 1297IsRepG2_label: 1298 UPDATE_1 probs_state, 0, (IsRepG2 - IsMatch) 1299 mov dist, rep3 1300 mov rep3, rep2 1301 mov rep2, rep1 1302 mov rep1, rep0 1303 mov rep0, dist 1304 jmp len_decode 1305 1306 1307 1308# ---------- SPEC SHORT DISTANCE ---------- 1309 1310MY_ALIGN_FOR_ENTRY 1311short_dist: 1312 p2_sub_s numBits, 32 + 1 1313 jbe decode_dist_end 1314 or sym, 2 1315 shl sym, numBits 1316 add sym_R, probs_Spec, sym_R, lsl #PSHIFT 1317 p2_add sym_R, SpecPos * PMULT + 1 * PMULT 1318 mov sym2, PMULT // # step 1319MY_ALIGN_FOR_LOOP 1320spec_loop: 1321 REV_1_VAR prob_reg 1322 dec_s numBits 1323 jnz spec_loop 1324 1325 p2_add sym2_R, probs_Spec 1326 .if SpecPos != 0 1327 p2_add sym2_R, SpecPos * PMULT 1328 .endif 1329 p2_sub sym_R, sym2_R 1330 shr sym, PSHIFT 1331 1332 jmp decode_dist_end 1333 1334 1335 1336# ---------- COPY MATCH 0 ---------- 1337MY_ALIGN_FOR_ENTRY 1338copy_match_0: 1339 #ifdef LZMA_USE_4BYTES_FILL 1340 strb sym, [dicPos, cnt_R] 1341 inc_s cnt_R 1342 jz copy_end 1343 1344 strb sym, [dicPos, cnt_R] 1345 inc_s cnt_R 1346 jz copy_end 1347 1348 strb sym, [dicPos, cnt_R] 1349 inc_s cnt_R 1350 jz copy_end 1351 1352 orr t3, sym, sym, lsl 8 1353 p2_and cnt_R, -4 1354 orr t3, t3, t3, lsl 16 1355MY_ALIGN_FOR_LOOP_16 13561: 1357 /* 1358 str t3, [dicPos, cnt_R] 1359 adds cnt_R, cnt_R, 4 1360 jz 2f 1361 */ 1362 1363 str t3, [dicPos, cnt_R] 1364 adds cnt_R, cnt_R, 4 1365 jnz 1b 13662: 1367 // p2_and sym, 255 1368 #else 1369 1370MY_ALIGN_FOR_LOOP 13711: 1372 strb sym, [dicPos, cnt_R] 1373 inc_s cnt_R 1374 jz copy_end 1375 1376 strb sym, [dicPos, cnt_R] 1377 inc_s cnt_R 1378 jnz 1b 1379 #endif 1380 1381 jmp copy_end 1382 1383 1384# ---------- COPY MATCH CROSS ---------- 1385copy_match_cross: 1386 # t0_R - src pos 1387 # cnt_R - total copy len 1388 1389 p1_neg cnt_R 13901: 1391 ldrb sym, [dic, t0_R] 1392 inc t0_R 1393 strb sym, [dicPos, cnt_R] 1394 inc cnt_R 1395 cmp t0_R, dicBufSize 1396 jne 1b 1397 1398 ldrb sym, [dic] 1399 sub t0_R, dic, cnt_R 1400 jmp copy_common 1401 1402 1403 1404 1405/* 1406fin_dicPos_LIMIT_REP_SHORT: 1407 mov len, 1 1408 jmp fin_OK 1409*/ 1410 1411/* 1412fin_dicPos_LIMIT: 1413 jmp fin_OK 1414 # For more strict mode we can stop decoding with error 1415 # mov sym, 1 1416 # jmp fin 1417*/ 1418 1419fin_ERROR_MATCH_DIST: 1420 # rep0 = distance + 1; 1421 p2_add len, kMatchSpecLen_Error_Data 1422 mov rep3, rep2 1423 mov rep2, rep1 1424 mov rep1, rep0 1425 mov rep0, sym 1426 STATE_UPDATE_FOR_MATCH 1427 # jmp fin_OK 1428 mov sym, 1 1429 jmp fin 1430 1431end_of_payload: 1432 inc_s sym 1433 jnz fin_ERROR_MATCH_DIST 1434 1435 mov len, kMatchSpecLenStart 1436 xor state, (1 << FLAG_STATE_BITS) 1437 jmp fin_OK 1438 1439/* 1440fin_OK_lit: 1441 mov len, wzr 1442*/ 1443 1444fin_OK: 1445 mov sym, wzr 1446 1447fin: 1448 NORM 1449 1450 #define fin_lzma_reg t0_R 1451 1452 .macro STORE_LZMA_VAR reg:req, struct_offs:req 1453 str \reg, [fin_lzma_reg, \struct_offs] 1454 .endm 1455 1456 .macro STORE_LZMA_PAIR reg0:req, reg1:req, struct_offs:req 1457 stp \reg0, \reg1, [fin_lzma_reg, \struct_offs] 1458 .endm 1459 1460 ldr fin_lzma_reg, [sp, 120] 1461 p2_sub dicPos, dic 1462 shr state, PSHIFT 1463 1464 STORE_LZMA_PAIR dicPos, buf, offset_dicPos 1465 STORE_LZMA_PAIR range, cod, offset_range 1466 STORE_LZMA_VAR processedPos, offset_processedPos 1467 STORE_LZMA_PAIR rep0, rep1, offset_rep0 1468 STORE_LZMA_PAIR rep2, rep3, offset_rep2 1469 STORE_LZMA_PAIR state, len, offset_state 1470 1471 mov w0, sym 1472 1473 ldp x29, x30, [sp, 80] 1474 ldp x27, x28, [sp, 64] 1475 ldp x25, x26, [sp, 48] 1476 ldp x23, x24, [sp, 32] 1477 ldp x21, x22, [sp, 16] 1478 ldp x19, x20, [sp], 128 1479 1480 ret 1481/* 1482 .cfi_endproc 1483.LFE0: 1484 .size LzmaDec_DecodeReal_3, .-LzmaDec_DecodeReal_3 1485 .ident "TAG_LZMA" 1486 .section .note.GNU-stack,"",@progbits 1487*/ 1488