1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * aes-ce-core.S - AES in CBC/CTR/XTS mode using ARMv8 Crypto Extensions 4 * 5 * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> 6 */ 7 8#include <linux/linkage.h> 9#include <asm/assembler.h> 10 11 .text 12 .fpu crypto-neon-fp-armv8 13 .align 3 14 15 .macro enc_round, state, key 16 aese.8 \state, \key 17 aesmc.8 \state, \state 18 .endm 19 20 .macro dec_round, state, key 21 aesd.8 \state, \key 22 aesimc.8 \state, \state 23 .endm 24 25 .macro enc_dround, key1, key2 26 enc_round q0, \key1 27 enc_round q0, \key2 28 .endm 29 30 .macro dec_dround, key1, key2 31 dec_round q0, \key1 32 dec_round q0, \key2 33 .endm 34 35 .macro enc_fround, key1, key2, key3 36 enc_round q0, \key1 37 aese.8 q0, \key2 38 veor q0, q0, \key3 39 .endm 40 41 .macro dec_fround, key1, key2, key3 42 dec_round q0, \key1 43 aesd.8 q0, \key2 44 veor q0, q0, \key3 45 .endm 46 47 .macro enc_dround_4x, key1, key2 48 enc_round q0, \key1 49 enc_round q1, \key1 50 enc_round q2, \key1 51 enc_round q3, \key1 52 enc_round q0, \key2 53 enc_round q1, \key2 54 enc_round q2, \key2 55 enc_round q3, \key2 56 .endm 57 58 .macro dec_dround_4x, key1, key2 59 dec_round q0, \key1 60 dec_round q1, \key1 61 dec_round q2, \key1 62 dec_round q3, \key1 63 dec_round q0, \key2 64 dec_round q1, \key2 65 dec_round q2, \key2 66 dec_round q3, \key2 67 .endm 68 69 .macro enc_fround_4x, key1, key2, key3 70 enc_round q0, \key1 71 enc_round q1, \key1 72 enc_round q2, \key1 73 enc_round q3, \key1 74 aese.8 q0, \key2 75 aese.8 q1, \key2 76 aese.8 q2, \key2 77 aese.8 q3, \key2 78 veor q0, q0, \key3 79 veor q1, q1, \key3 80 veor q2, q2, \key3 81 veor q3, q3, \key3 82 .endm 83 84 .macro dec_fround_4x, key1, key2, key3 85 dec_round q0, \key1 86 dec_round q1, \key1 87 dec_round q2, \key1 88 dec_round q3, \key1 89 aesd.8 q0, \key2 90 aesd.8 q1, \key2 91 aesd.8 q2, \key2 92 aesd.8 q3, \key2 93 veor q0, q0, \key3 94 veor q1, q1, \key3 95 veor q2, q2, \key3 96 veor q3, q3, \key3 97 .endm 98 99 .macro do_block, dround, fround 100 cmp r3, #12 @ which key size? 101 vld1.32 {q10-q11}, [ip]! 102 \dround q8, q9 103 vld1.32 {q12-q13}, [ip]! 104 \dround q10, q11 105 vld1.32 {q10-q11}, [ip]! 106 \dround q12, q13 107 vld1.32 {q12-q13}, [ip]! 108 \dround q10, q11 109 blo 0f @ AES-128: 10 rounds 110 vld1.32 {q10-q11}, [ip]! 111 \dround q12, q13 112 beq 1f @ AES-192: 12 rounds 113 vld1.32 {q12-q13}, [ip] 114 \dround q10, q11 1150: \fround q12, q13, q14 116 bx lr 117 1181: \fround q10, q11, q14 119 bx lr 120 .endm 121 122 /* 123 * Internal, non-AAPCS compliant functions that implement the core AES 124 * transforms. These should preserve all registers except q0 - q2 and ip 125 * Arguments: 126 * q0 : first in/output block 127 * q1 : second in/output block (_4x version only) 128 * q2 : third in/output block (_4x version only) 129 * q3 : fourth in/output block (_4x version only) 130 * q8 : first round key 131 * q9 : secound round key 132 * q14 : final round key 133 * r2 : address of round key array 134 * r3 : number of rounds 135 */ 136 .align 6 137aes_encrypt: 138 add ip, r2, #32 @ 3rd round key 139.Laes_encrypt_tweak: 140 do_block enc_dround, enc_fround 141ENDPROC(aes_encrypt) 142 143 .align 6 144aes_decrypt: 145 add ip, r2, #32 @ 3rd round key 146 do_block dec_dround, dec_fround 147ENDPROC(aes_decrypt) 148 149 .align 6 150aes_encrypt_4x: 151 add ip, r2, #32 @ 3rd round key 152 do_block enc_dround_4x, enc_fround_4x 153ENDPROC(aes_encrypt_4x) 154 155 .align 6 156aes_decrypt_4x: 157 add ip, r2, #32 @ 3rd round key 158 do_block dec_dround_4x, dec_fround_4x 159ENDPROC(aes_decrypt_4x) 160 161 .macro prepare_key, rk, rounds 162 add ip, \rk, \rounds, lsl #4 163 vld1.32 {q8-q9}, [\rk] @ load first 2 round keys 164 vld1.32 {q14}, [ip] @ load last round key 165 .endm 166 167 /* 168 * aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, 169 * int blocks) 170 * aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, 171 * int blocks) 172 */ 173ENTRY(ce_aes_ecb_encrypt) 174 push {r4, lr} 175 ldr r4, [sp, #8] 176 prepare_key r2, r3 177.Lecbencloop4x: 178 subs r4, r4, #4 179 bmi .Lecbenc1x 180 vld1.8 {q0-q1}, [r1]! 181 vld1.8 {q2-q3}, [r1]! 182 bl aes_encrypt_4x 183 vst1.8 {q0-q1}, [r0]! 184 vst1.8 {q2-q3}, [r0]! 185 b .Lecbencloop4x 186.Lecbenc1x: 187 adds r4, r4, #4 188 beq .Lecbencout 189.Lecbencloop: 190 vld1.8 {q0}, [r1]! 191 bl aes_encrypt 192 vst1.8 {q0}, [r0]! 193 subs r4, r4, #1 194 bne .Lecbencloop 195.Lecbencout: 196 pop {r4, pc} 197ENDPROC(ce_aes_ecb_encrypt) 198 199ENTRY(ce_aes_ecb_decrypt) 200 push {r4, lr} 201 ldr r4, [sp, #8] 202 prepare_key r2, r3 203.Lecbdecloop4x: 204 subs r4, r4, #4 205 bmi .Lecbdec1x 206 vld1.8 {q0-q1}, [r1]! 207 vld1.8 {q2-q3}, [r1]! 208 bl aes_decrypt_4x 209 vst1.8 {q0-q1}, [r0]! 210 vst1.8 {q2-q3}, [r0]! 211 b .Lecbdecloop4x 212.Lecbdec1x: 213 adds r4, r4, #4 214 beq .Lecbdecout 215.Lecbdecloop: 216 vld1.8 {q0}, [r1]! 217 bl aes_decrypt 218 vst1.8 {q0}, [r0]! 219 subs r4, r4, #1 220 bne .Lecbdecloop 221.Lecbdecout: 222 pop {r4, pc} 223ENDPROC(ce_aes_ecb_decrypt) 224 225 /* 226 * aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, 227 * int blocks, u8 iv[]) 228 * aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, 229 * int blocks, u8 iv[]) 230 */ 231ENTRY(ce_aes_cbc_encrypt) 232 push {r4-r6, lr} 233 ldrd r4, r5, [sp, #16] 234 vld1.8 {q0}, [r5] 235 prepare_key r2, r3 236.Lcbcencloop: 237 vld1.8 {q1}, [r1]! @ get next pt block 238 veor q0, q0, q1 @ ..and xor with iv 239 bl aes_encrypt 240 vst1.8 {q0}, [r0]! 241 subs r4, r4, #1 242 bne .Lcbcencloop 243 vst1.8 {q0}, [r5] 244 pop {r4-r6, pc} 245ENDPROC(ce_aes_cbc_encrypt) 246 247ENTRY(ce_aes_cbc_decrypt) 248 push {r4-r6, lr} 249 ldrd r4, r5, [sp, #16] 250 vld1.8 {q15}, [r5] @ keep iv in q15 251 prepare_key r2, r3 252.Lcbcdecloop4x: 253 subs r4, r4, #4 254 bmi .Lcbcdec1x 255 vld1.8 {q0-q1}, [r1]! 256 vld1.8 {q2-q3}, [r1]! 257 vmov q4, q0 258 vmov q5, q1 259 vmov q6, q2 260 vmov q7, q3 261 bl aes_decrypt_4x 262 veor q0, q0, q15 263 veor q1, q1, q4 264 veor q2, q2, q5 265 veor q3, q3, q6 266 vmov q15, q7 267 vst1.8 {q0-q1}, [r0]! 268 vst1.8 {q2-q3}, [r0]! 269 b .Lcbcdecloop4x 270.Lcbcdec1x: 271 adds r4, r4, #4 272 beq .Lcbcdecout 273 vmov q6, q14 @ preserve last round key 274.Lcbcdecloop: 275 vld1.8 {q0}, [r1]! @ get next ct block 276 veor q14, q15, q6 @ combine prev ct with last key 277 vmov q15, q0 278 bl aes_decrypt 279 vst1.8 {q0}, [r0]! 280 subs r4, r4, #1 281 bne .Lcbcdecloop 282.Lcbcdecout: 283 vst1.8 {q15}, [r5] @ keep iv in q15 284 pop {r4-r6, pc} 285ENDPROC(ce_aes_cbc_decrypt) 286 287 288 /* 289 * ce_aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const rk[], 290 * int rounds, int bytes, u8 const iv[]) 291 * ce_aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const rk[], 292 * int rounds, int bytes, u8 const iv[]) 293 */ 294 295ENTRY(ce_aes_cbc_cts_encrypt) 296 push {r4-r6, lr} 297 ldrd r4, r5, [sp, #16] 298 299 movw ip, :lower16:.Lcts_permute_table 300 movt ip, :upper16:.Lcts_permute_table 301 sub r4, r4, #16 302 add lr, ip, #32 303 add ip, ip, r4 304 sub lr, lr, r4 305 vld1.8 {q5}, [ip] 306 vld1.8 {q6}, [lr] 307 308 add ip, r1, r4 309 vld1.8 {q0}, [r1] @ overlapping loads 310 vld1.8 {q3}, [ip] 311 312 vld1.8 {q1}, [r5] @ get iv 313 prepare_key r2, r3 314 315 veor q0, q0, q1 @ xor with iv 316 bl aes_encrypt 317 318 vtbl.8 d4, {d0-d1}, d10 319 vtbl.8 d5, {d0-d1}, d11 320 vtbl.8 d2, {d6-d7}, d12 321 vtbl.8 d3, {d6-d7}, d13 322 323 veor q0, q0, q1 324 bl aes_encrypt 325 326 add r4, r0, r4 327 vst1.8 {q2}, [r4] @ overlapping stores 328 vst1.8 {q0}, [r0] 329 330 pop {r4-r6, pc} 331ENDPROC(ce_aes_cbc_cts_encrypt) 332 333ENTRY(ce_aes_cbc_cts_decrypt) 334 push {r4-r6, lr} 335 ldrd r4, r5, [sp, #16] 336 337 movw ip, :lower16:.Lcts_permute_table 338 movt ip, :upper16:.Lcts_permute_table 339 sub r4, r4, #16 340 add lr, ip, #32 341 add ip, ip, r4 342 sub lr, lr, r4 343 vld1.8 {q5}, [ip] 344 vld1.8 {q6}, [lr] 345 346 add ip, r1, r4 347 vld1.8 {q0}, [r1] @ overlapping loads 348 vld1.8 {q1}, [ip] 349 350 vld1.8 {q3}, [r5] @ get iv 351 prepare_key r2, r3 352 353 bl aes_decrypt 354 355 vtbl.8 d4, {d0-d1}, d10 356 vtbl.8 d5, {d0-d1}, d11 357 vtbx.8 d0, {d2-d3}, d12 358 vtbx.8 d1, {d2-d3}, d13 359 360 veor q1, q1, q2 361 bl aes_decrypt 362 veor q0, q0, q3 @ xor with iv 363 364 add r4, r0, r4 365 vst1.8 {q1}, [r4] @ overlapping stores 366 vst1.8 {q0}, [r0] 367 368 pop {r4-r6, pc} 369ENDPROC(ce_aes_cbc_cts_decrypt) 370 371 372 /* 373 * aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, 374 * int blocks, u8 ctr[]) 375 */ 376ENTRY(ce_aes_ctr_encrypt) 377 push {r4-r6, lr} 378 ldrd r4, r5, [sp, #16] 379 vld1.8 {q7}, [r5] @ load ctr 380 prepare_key r2, r3 381 vmov r6, s31 @ keep swabbed ctr in r6 382 rev r6, r6 383 cmn r6, r4 @ 32 bit overflow? 384 bcs .Lctrloop 385.Lctrloop4x: 386 subs r4, r4, #4 387 bmi .Lctr1x 388 add r6, r6, #1 389 vmov q0, q7 390 vmov q1, q7 391 rev ip, r6 392 add r6, r6, #1 393 vmov q2, q7 394 vmov s7, ip 395 rev ip, r6 396 add r6, r6, #1 397 vmov q3, q7 398 vmov s11, ip 399 rev ip, r6 400 add r6, r6, #1 401 vmov s15, ip 402 vld1.8 {q4-q5}, [r1]! 403 vld1.8 {q6}, [r1]! 404 vld1.8 {q15}, [r1]! 405 bl aes_encrypt_4x 406 veor q0, q0, q4 407 veor q1, q1, q5 408 veor q2, q2, q6 409 veor q3, q3, q15 410 rev ip, r6 411 vst1.8 {q0-q1}, [r0]! 412 vst1.8 {q2-q3}, [r0]! 413 vmov s31, ip 414 b .Lctrloop4x 415.Lctr1x: 416 adds r4, r4, #4 417 beq .Lctrout 418.Lctrloop: 419 vmov q0, q7 420 bl aes_encrypt 421 422 adds r6, r6, #1 @ increment BE ctr 423 rev ip, r6 424 vmov s31, ip 425 bcs .Lctrcarry 426 427.Lctrcarrydone: 428 subs r4, r4, #1 429 bmi .Lctrtailblock @ blocks < 0 means tail block 430 vld1.8 {q3}, [r1]! 431 veor q3, q0, q3 432 vst1.8 {q3}, [r0]! 433 bne .Lctrloop 434 435.Lctrout: 436 vst1.8 {q7}, [r5] @ return next CTR value 437 pop {r4-r6, pc} 438 439.Lctrtailblock: 440 vst1.8 {q0}, [r0, :64] @ return the key stream 441 b .Lctrout 442 443.Lctrcarry: 444 .irp sreg, s30, s29, s28 445 vmov ip, \sreg @ load next word of ctr 446 rev ip, ip @ ... to handle the carry 447 adds ip, ip, #1 448 rev ip, ip 449 vmov \sreg, ip 450 bcc .Lctrcarrydone 451 .endr 452 b .Lctrcarrydone 453ENDPROC(ce_aes_ctr_encrypt) 454 455 /* 456 * aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[], int rounds, 457 * int bytes, u8 iv[], u32 const rk2[], int first) 458 * aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[], int rounds, 459 * int bytes, u8 iv[], u32 const rk2[], int first) 460 */ 461 462 .macro next_tweak, out, in, const, tmp 463 vshr.s64 \tmp, \in, #63 464 vand \tmp, \tmp, \const 465 vadd.u64 \out, \in, \in 466 vext.8 \tmp, \tmp, \tmp, #8 467 veor \out, \out, \tmp 468 .endm 469 470ce_aes_xts_init: 471 vmov.i32 d30, #0x87 @ compose tweak mask vector 472 vmovl.u32 q15, d30 473 vshr.u64 d30, d31, #7 474 475 ldrd r4, r5, [sp, #16] @ load args 476 ldr r6, [sp, #28] 477 vld1.8 {q0}, [r5] @ load iv 478 teq r6, #1 @ start of a block? 479 bxne lr 480 481 @ Encrypt the IV in q0 with the second AES key. This should only 482 @ be done at the start of a block. 483 ldr r6, [sp, #24] @ load AES key 2 484 prepare_key r6, r3 485 add ip, r6, #32 @ 3rd round key of key 2 486 b .Laes_encrypt_tweak @ tail call 487ENDPROC(ce_aes_xts_init) 488 489ENTRY(ce_aes_xts_encrypt) 490 push {r4-r6, lr} 491 492 bl ce_aes_xts_init @ run shared prologue 493 prepare_key r2, r3 494 vmov q4, q0 495 496 teq r6, #0 @ start of a block? 497 bne .Lxtsenc4x 498 499.Lxtsencloop4x: 500 next_tweak q4, q4, q15, q10 501.Lxtsenc4x: 502 subs r4, r4, #64 503 bmi .Lxtsenc1x 504 vld1.8 {q0-q1}, [r1]! @ get 4 pt blocks 505 vld1.8 {q2-q3}, [r1]! 506 next_tweak q5, q4, q15, q10 507 veor q0, q0, q4 508 next_tweak q6, q5, q15, q10 509 veor q1, q1, q5 510 next_tweak q7, q6, q15, q10 511 veor q2, q2, q6 512 veor q3, q3, q7 513 bl aes_encrypt_4x 514 veor q0, q0, q4 515 veor q1, q1, q5 516 veor q2, q2, q6 517 veor q3, q3, q7 518 vst1.8 {q0-q1}, [r0]! @ write 4 ct blocks 519 vst1.8 {q2-q3}, [r0]! 520 vmov q4, q7 521 teq r4, #0 522 beq .Lxtsencret 523 b .Lxtsencloop4x 524.Lxtsenc1x: 525 adds r4, r4, #64 526 beq .Lxtsencout 527 subs r4, r4, #16 528 bmi .LxtsencctsNx 529.Lxtsencloop: 530 vld1.8 {q0}, [r1]! 531.Lxtsencctsout: 532 veor q0, q0, q4 533 bl aes_encrypt 534 veor q0, q0, q4 535 teq r4, #0 536 beq .Lxtsencout 537 subs r4, r4, #16 538 next_tweak q4, q4, q15, q6 539 bmi .Lxtsenccts 540 vst1.8 {q0}, [r0]! 541 b .Lxtsencloop 542.Lxtsencout: 543 vst1.8 {q0}, [r0] 544.Lxtsencret: 545 vst1.8 {q4}, [r5] 546 pop {r4-r6, pc} 547 548.LxtsencctsNx: 549 vmov q0, q3 550 sub r0, r0, #16 551.Lxtsenccts: 552 movw ip, :lower16:.Lcts_permute_table 553 movt ip, :upper16:.Lcts_permute_table 554 555 add r1, r1, r4 @ rewind input pointer 556 add r4, r4, #16 @ # bytes in final block 557 add lr, ip, #32 558 add ip, ip, r4 559 sub lr, lr, r4 560 add r4, r0, r4 @ output address of final block 561 562 vld1.8 {q1}, [r1] @ load final partial block 563 vld1.8 {q2}, [ip] 564 vld1.8 {q3}, [lr] 565 566 vtbl.8 d4, {d0-d1}, d4 567 vtbl.8 d5, {d0-d1}, d5 568 vtbx.8 d0, {d2-d3}, d6 569 vtbx.8 d1, {d2-d3}, d7 570 571 vst1.8 {q2}, [r4] @ overlapping stores 572 mov r4, #0 573 b .Lxtsencctsout 574ENDPROC(ce_aes_xts_encrypt) 575 576 577ENTRY(ce_aes_xts_decrypt) 578 push {r4-r6, lr} 579 580 bl ce_aes_xts_init @ run shared prologue 581 prepare_key r2, r3 582 vmov q4, q0 583 584 /* subtract 16 bytes if we are doing CTS */ 585 tst r4, #0xf 586 subne r4, r4, #0x10 587 588 teq r6, #0 @ start of a block? 589 bne .Lxtsdec4x 590 591.Lxtsdecloop4x: 592 next_tweak q4, q4, q15, q10 593.Lxtsdec4x: 594 subs r4, r4, #64 595 bmi .Lxtsdec1x 596 vld1.8 {q0-q1}, [r1]! @ get 4 ct blocks 597 vld1.8 {q2-q3}, [r1]! 598 next_tweak q5, q4, q15, q10 599 veor q0, q0, q4 600 next_tweak q6, q5, q15, q10 601 veor q1, q1, q5 602 next_tweak q7, q6, q15, q10 603 veor q2, q2, q6 604 veor q3, q3, q7 605 bl aes_decrypt_4x 606 veor q0, q0, q4 607 veor q1, q1, q5 608 veor q2, q2, q6 609 veor q3, q3, q7 610 vst1.8 {q0-q1}, [r0]! @ write 4 pt blocks 611 vst1.8 {q2-q3}, [r0]! 612 vmov q4, q7 613 teq r4, #0 614 beq .Lxtsdecout 615 b .Lxtsdecloop4x 616.Lxtsdec1x: 617 adds r4, r4, #64 618 beq .Lxtsdecout 619 subs r4, r4, #16 620.Lxtsdecloop: 621 vld1.8 {q0}, [r1]! 622 bmi .Lxtsdeccts 623.Lxtsdecctsout: 624 veor q0, q0, q4 625 bl aes_decrypt 626 veor q0, q0, q4 627 vst1.8 {q0}, [r0]! 628 teq r4, #0 629 beq .Lxtsdecout 630 subs r4, r4, #16 631 next_tweak q4, q4, q15, q6 632 b .Lxtsdecloop 633.Lxtsdecout: 634 vst1.8 {q4}, [r5] 635 pop {r4-r6, pc} 636 637.Lxtsdeccts: 638 movw ip, :lower16:.Lcts_permute_table 639 movt ip, :upper16:.Lcts_permute_table 640 641 add r1, r1, r4 @ rewind input pointer 642 add r4, r4, #16 @ # bytes in final block 643 add lr, ip, #32 644 add ip, ip, r4 645 sub lr, lr, r4 646 add r4, r0, r4 @ output address of final block 647 648 next_tweak q5, q4, q15, q6 649 650 vld1.8 {q1}, [r1] @ load final partial block 651 vld1.8 {q2}, [ip] 652 vld1.8 {q3}, [lr] 653 654 veor q0, q0, q5 655 bl aes_decrypt 656 veor q0, q0, q5 657 658 vtbl.8 d4, {d0-d1}, d4 659 vtbl.8 d5, {d0-d1}, d5 660 vtbx.8 d0, {d2-d3}, d6 661 vtbx.8 d1, {d2-d3}, d7 662 663 vst1.8 {q2}, [r4] @ overlapping stores 664 mov r4, #0 665 b .Lxtsdecctsout 666ENDPROC(ce_aes_xts_decrypt) 667 668 /* 669 * u32 ce_aes_sub(u32 input) - use the aese instruction to perform the 670 * AES sbox substitution on each byte in 671 * 'input' 672 */ 673ENTRY(ce_aes_sub) 674 vdup.32 q1, r0 675 veor q0, q0, q0 676 aese.8 q0, q1 677 vmov r0, s0 678 bx lr 679ENDPROC(ce_aes_sub) 680 681 /* 682 * void ce_aes_invert(u8 *dst, u8 *src) - perform the Inverse MixColumns 683 * operation on round key *src 684 */ 685ENTRY(ce_aes_invert) 686 vld1.32 {q0}, [r1] 687 aesimc.8 q0, q0 688 vst1.32 {q0}, [r0] 689 bx lr 690ENDPROC(ce_aes_invert) 691 692 .section ".rodata", "a" 693 .align 6 694.Lcts_permute_table: 695 .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 696 .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 697 .byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 698 .byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf 699 .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 700 .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 701