1 ;// 2 ;// Copyright (C) 2007-2008 ARM Limited 3 ;// 4 ;// Licensed under the Apache License, Version 2.0 (the "License"); 5 ;// you may not use this file except in compliance with the License. 6 ;// You may obtain a copy of the License at 7 ;// 8 ;// http://www.apache.org/licenses/LICENSE-2.0 9 ;// 10 ;// Unless required by applicable law or agreed to in writing, software 11 ;// distributed under the License is distributed on an "AS IS" BASIS, 12 ;// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ;// See the License for the specific language governing permissions and 14 ;// limitations under the License. 15 ;// 16 ;// 17 ;// 18 ;// File Name: armCOMM_s.h 19 ;// OpenMAX DL: v1.0.2 20 ;// Revision: 12290 21 ;// Date: Wednesday, April 9, 2008 22 ;// 23 ;// 24 ;// 25 ;// 26 ;// ARM optimized OpenMAX common header file 27 ;// 28 29 ;// Protect against multiple inclusion 30 IF :LNOT::DEF:ARMCOMM_S_H 31 GBLL ARMCOMM_S_H 32 33 REQUIRE8 ;// Requires 8-byte stack alignment 34 PRESERVE8 ;// Preserves 8-byte stack alignment 35 36 GBLL ARM_ERRORCHECK 37 ARM_ERRORCHECK SETL {FALSE} 38 39 ;// Globals 40 41 GBLS _RRegList ;// R saved register list 42 GBLS _DRegList ;// D saved register list 43 GBLS _Variant ;// Selected processor variant 44 GBLS _CPU ;// CPU name 45 GBLS _Struct ;// Structure name 46 47 GBLL _InFunc ;// Inside function assembly flag 48 GBLL _SwLong ;// Long switch flag 49 50 GBLA _RBytes ;// Number of register bytes on stack 51 GBLA _SBytes ;// Number of scratch bytes on stack 52 GBLA _ABytes ;// Stack offset of next argument 53 GBLA _Workspace ;// Stack offset of scratch workspace 54 GBLA _F ;// Function number 55 GBLA _StOff ;// Struct offset 56 GBLA _SwNum ;// Switch number 57 GBLS _32 ;// Suffix for 32 byte alignmnet 58 GBLS _16 ;// Suffix for 16 byte alignmnet 59 60 _InFunc SETL {FALSE} 61 _SBytes SETA 0 62 _F SETA 0 63 _SwNum SETA 0 64 _32 SETS "ALIGN32" 65 _16 SETS "ALIGN16" 66 67 ;///////////////////////////////////////////////////////// 68 ;// Override the tools settings of the CPU if the #define 69 ;// USECPU is set, otherwise use the CPU defined by the 70 ;// assembler settings. 71 ;///////////////////////////////////////////////////////// 72 73 IF :DEF: OVERRIDECPU 74 _CPU SETS OVERRIDECPU 75 ELSE 76 _CPU SETS {CPU} 77 ENDIF 78 79 80 81 ;///////////////////////////////////////////////////////// 82 ;// Work out which code to build 83 ;///////////////////////////////////////////////////////// 84 85 IF :DEF:ARM1136JS:LOR::DEF:CortexA8:LOR::DEF:ARM_GENERIC 86 INFO 1,"Please switch to using M_VARIANTS" 87 ENDIF 88 89 ;// Define and reset all officially recongnised variants 90 MACRO 91 _M_DEF_VARIANTS 92 _M_DEF_VARIANT ARM926EJS 93 _M_DEF_VARIANT ARM1136JS 94 _M_DEF_VARIANT ARM1136JS_U 95 _M_DEF_VARIANT CortexA8 96 _M_DEF_VARIANT ARM7TDMI 97 MEND 98 99 MACRO 100 _M_DEF_VARIANT $var 101 GBLL $var 102 GBLL _ok$var 103 $var SETL {FALSE} 104 MEND 105 106 107 ;// Variant declaration 108 ;// 109 ;// Define a list of code variants supported by this 110 ;// source file. This macro then chooses the most 111 ;// appropriate variant to build for the currently configured 112 ;// core. 113 ;// 114 MACRO 115 M_VARIANTS $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7 116 ;// Set to TRUE variants that are supported 117 _M_DEF_VARIANTS 118 _M_VARIANT $v0 119 _M_VARIANT $v1 120 _M_VARIANT $v2 121 _M_VARIANT $v3 122 _M_VARIANT $v4 123 _M_VARIANT $v5 124 _M_VARIANT $v6 125 _M_VARIANT $v7 126 127 ;// Look for first available variant to match a CPU 128 ;// _M_TRY cpu, variant fall back list 129 _Variant SETS "" 130 _M_TRY ARM926EJ-S, ARM926EJS 131 _M_TRY ARM1176JZ-S, ARM1136JS 132 _M_TRY ARM1176JZF-S, ARM1136JS 133 _M_TRY ARM1156T2-S, ARM1136JS 134 _M_TRY ARM1156T2F-S, ARM1136JS 135 _M_TRY ARM1136J-S, ARM1136JS 136 _M_TRY ARM1136JF-S, ARM1136JS 137 _M_TRY MPCore, ARM1136JS 138 _M_TRY falcon-vfp, ARM1136JS 139 _M_TRY falcon-full-neon, CortexA8 140 _M_TRY Cortex-A8NoNeon, ARM1136JS 141 _M_TRY Cortex-A8, CortexA8, ARM1136JS 142 _M_TRY Cortex-R4, ARM1136JS 143 _M_TRY ARM7TDMI 144 145 ;// Select the correct variant 146 _M_DEF_VARIANTS 147 IF _Variant="" 148 INFO 1, "No match found for CPU '$_CPU'" 149 ELSE 150 $_Variant SETL {TRUE} 151 ENDIF 152 MEND 153 154 ;// Register a variant as available 155 MACRO 156 _M_VARIANT $var 157 IF "$var"="" 158 MEXIT 159 ENDIF 160 IF :LNOT::DEF:_ok$var 161 INFO 1, "Unrecognized variant '$var'" 162 ENDIF 163 $var SETL {TRUE} 164 MEND 165 166 ;// For a given CPU, see if any of the variants supporting 167 ;// this CPU are available. The first available variant is 168 ;// chosen 169 MACRO 170 _M_TRY $cpu, $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7 171 IF "$cpu"<>_CPU 172 MEXIT 173 ENDIF 174 _M_TRY1 $v0 175 _M_TRY1 $v1 176 _M_TRY1 $v2 177 _M_TRY1 $v3 178 _M_TRY1 $v4 179 _M_TRY1 $v5 180 _M_TRY1 $v6 181 _M_TRY1 $v7 182 ;// Check a match was found 183 IF _Variant="" 184 INFO 1, "No variant match found for CPU '$_CPU'" 185 ENDIF 186 MEND 187 188 MACRO 189 _M_TRY1 $var 190 IF "$var"="" 191 MEXIT 192 ENDIF 193 IF (_Variant=""):LAND:$var 194 _Variant SETS "$var" 195 ENDIF 196 MEND 197 198 ;//////////////////////////////////////////////////////// 199 ;// Structure definition 200 ;//////////////////////////////////////////////////////// 201 202 ;// Declare a structure of given name 203 MACRO 204 M_STRUCT $sname 205 _Struct SETS "$sname" 206 _StOff SETA 0 207 MEND 208 209 ;// Declare a structure field 210 ;// The field is called $sname_$fname 211 ;// $size = the size of each entry, must be power of 2 212 ;// $number = (if provided) the number of entries for an array 213 MACRO 214 M_FIELD $fname, $size, $number 215 IF (_StOff:AND:($size-1))!=0 216 _StOff SETA _StOff + ($size - (_StOff:AND:($size-1))) 217 ENDIF 218 $_Struct._$fname EQU _StOff 219 IF "$number"<>"" 220 _StOff SETA _StOff + $size*$number 221 ELSE 222 _StOff SETA _StOff + $size 223 ENDIF 224 MEND 225 226 227 MACRO 228 M_ENDSTRUCT 229 sizeof_$_Struct EQU _StOff 230 _Struct SETS "" 231 MEND 232 233 ;////////////////////////////////////////////////////////// 234 ;// Switch and table macros 235 ;////////////////////////////////////////////////////////// 236 237 ;// Start a relative switch table with register to switch on 238 ;// 239 ;// $v = the register to switch on 240 ;// $s = if specified must be "L" to indicate long 241 ;// this allows a greater range to the case code 242 MACRO 243 M_SWITCH $v, $s 244 ASSERT "$s"="":LOR:"$s"="L" 245 _SwLong SETL {FALSE} 246 IF "$s"="L" 247 _SwLong SETL {TRUE} 248 ENDIF 249 _SwNum SETA _SwNum+1 250 IF {CONFIG}=16 251 ;// Thumb 252 IF _SwLong 253 TBH [pc, $v, LSL#1] 254 ELSE 255 TBB [pc, $v] 256 ENDIF 257 _Switch$_SwNum 258 ELSE 259 ;// ARM 260 ADD pc, pc, $v, LSL #2 261 NOP 262 ENDIF 263 MEND 264 265 ;// Add a case to the switch statement 266 MACRO 267 M_CASE $label 268 IF {CONFIG}=16 269 ;// Thumb 270 IF _SwLong 271 DCW ($label - _Switch$_SwNum)/2 272 ELSE 273 DCB ($label - _Switch$_SwNum)/2 274 ENDIF 275 ELSE 276 ;// ARM 277 B $label 278 ENDIF 279 MEND 280 281 ;// End of switch statement 282 MACRO 283 M_ENDSWITCH 284 ALIGN 2 285 MEND 286 287 288 ;//////////////////////////////////////////////////////// 289 ;// Data area allocation 290 ;//////////////////////////////////////////////////////// 291 292 ;// Constant table allocator macro 293 ;// 294 ;// Creates a new section for each constant table 295 ;// $name is symbol through which the table can be accessed. 296 ;// $align is the optional alignment of the table, log2 of 297 ;// the byte alignment - $align=4 is 16 byte aligned 298 MACRO 299 M_TABLE $name, $align 300 ASSERT :LNOT:_InFunc 301 IF "$align"="" 302 AREA |.constdata|, READONLY, DATA 303 ELSE 304 ;// AREAs inherit the alignment of the first declaration. 305 ;// Therefore for each alignment size we must have an area 306 ;// of a different name. 307 AREA constdata_a$align, READONLY, DATA, ALIGN=$align 308 309 ;// We also force alignment incase we are tagging onto 310 ;// an already started area. 311 ALIGN (1<<$align) 312 ENDIF 313 $name 314 MEND 315 316 ;///////////////////////////////////////////////////// 317 ;// Macros to allocate space on the stack 318 ;// 319 ;// These all assume that the stack is 8-byte aligned 320 ;// at entry to the function, which means that the 321 ;// 32-byte alignment macro needs to work in a 322 ;// bit more of a special way... 323 ;///////////////////////////////////////////////////// 324 325 326 327 328 ;// Allocate 1-byte aligned area of name 329 ;// $name size $size bytes. 330 MACRO 331 M_ALLOC1 $name, $size 332 ASSERT :LNOT:_InFunc 333 $name$_F EQU _SBytes 334 _SBytes SETA _SBytes + ($size) 335 MEND 336 337 ;// Allocate 2-byte aligned area of name 338 ;// $name size $size bytes. 339 MACRO 340 M_ALLOC2 $name, $size 341 ASSERT :LNOT:_InFunc 342 IF (_SBytes:AND:1)!=0 343 _SBytes SETA _SBytes + (2 - (_SBytes:AND:1)) 344 ENDIF 345 $name$_F EQU _SBytes 346 _SBytes SETA _SBytes + ($size) 347 MEND 348 349 ;// Allocate 4-byte aligned area of name 350 ;// $name size $size bytes. 351 MACRO 352 M_ALLOC4 $name, $size 353 ASSERT :LNOT:_InFunc 354 IF (_SBytes:AND:3)!=0 355 _SBytes SETA _SBytes + (4 - (_SBytes:AND:3)) 356 ENDIF 357 $name$_F EQU _SBytes 358 _SBytes SETA _SBytes + ($size) 359 MEND 360 361 ;// Allocate 8-byte aligned area of name 362 ;// $name size $size bytes. 363 MACRO 364 M_ALLOC8 $name, $size 365 ASSERT :LNOT:_InFunc 366 IF (_SBytes:AND:7)!=0 367 _SBytes SETA _SBytes + (8 - (_SBytes:AND:7)) 368 ENDIF 369 $name$_F EQU _SBytes 370 _SBytes SETA _SBytes + ($size) 371 MEND 372 373 374 ;// Allocate 8-byte aligned area of name 375 ;// $name size ($size+16) bytes. 376 ;// The extra 16 bytes are later used to align the pointer to 16 bytes 377 378 MACRO 379 M_ALLOC16 $name, $size 380 ASSERT :LNOT:_InFunc 381 IF (_SBytes:AND:7)!=0 382 _SBytes SETA _SBytes + (8 - (_SBytes:AND:7)) 383 ENDIF 384 $name$_F$_16 EQU (_SBytes + 8) 385 _SBytes SETA _SBytes + ($size) + 8 386 MEND 387 388 ;// Allocate 8-byte aligned area of name 389 ;// $name size ($size+32) bytes. 390 ;// The extra 32 bytes are later used to align the pointer to 32 bytes 391 392 MACRO 393 M_ALLOC32 $name, $size 394 ASSERT :LNOT:_InFunc 395 IF (_SBytes:AND:7)!=0 396 _SBytes SETA _SBytes + (8 - (_SBytes:AND:7)) 397 ENDIF 398 $name$_F$_32 EQU (_SBytes + 24) 399 _SBytes SETA _SBytes + ($size) + 24 400 MEND 401 402 403 404 405 ;// Argument Declaration Macro 406 ;// 407 ;// Allocate an argument name $name 408 ;// size $size bytes 409 MACRO 410 M_ARG $name, $size 411 ASSERT _InFunc 412 $name$_F EQU _ABytes 413 _ABytes SETA _ABytes + ($size) 414 MEND 415 416 ;/////////////////////////////////////////////// 417 ;// Macros to access stacked variables 418 ;/////////////////////////////////////////////// 419 420 ;// Macro to perform a data processing operation 421 ;// with a constant second operand 422 MACRO 423 _M_OPC $op,$rd,$rn,$const 424 LCLA _sh 425 LCLA _cst 426 _sh SETA 0 427 _cst SETA $const 428 IF _cst=0 429 $op $rd, $rn, #_cst 430 MEXIT 431 ENDIF 432 WHILE (_cst:AND:3)=0 433 _cst SETA _cst>>2 434 _sh SETA _sh+2 435 WEND 436 $op $rd, $rn, #(_cst:AND:0x000000FF)<<_sh 437 IF _cst>=256 438 $op $rd, $rd, #(_cst:AND:0xFFFFFF00)<<_sh 439 ENDIF 440 MEND 441 442 ;// Macro to perform a data access operation 443 ;// Such as LDR or STR 444 ;// The addressing mode is modified such that 445 ;// 1. If no address is given then the name is taken 446 ;// as a stack offset 447 ;// 2. If the addressing mode is not available for the 448 ;// state being assembled for (eg Thumb) then a suitable 449 ;// addressing mode is substituted. 450 ;// 451 ;// On Entry: 452 ;// $i = Instruction to perform (eg "LDRB") 453 ;// $a = Required byte alignment 454 ;// $r = Register(s) to transfer (eg "r1") 455 ;// $a0,$a1,$a2. Addressing mode and condition. One of: 456 ;// label {,cc} 457 ;// [base] {,,,cc} 458 ;// [base, offset]{!} {,,cc} 459 ;// [base, offset, shift]{!} {,cc} 460 ;// [base], offset {,,cc} 461 ;// [base], offset, shift {,cc} 462 MACRO 463 _M_DATA $i,$a,$r,$a0,$a1,$a2,$a3 464 IF "$a0":LEFT:1="[" 465 IF "$a1"="" 466 $i$a3 $r, $a0 467 ELSE 468 IF "$a0":RIGHT:1="]" 469 IF "$a2"="" 470 _M_POSTIND $i$a3, "$r", $a0, $a1 471 ELSE 472 _M_POSTIND $i$a3, "$r", $a0, "$a1,$a2" 473 ENDIF 474 ELSE 475 IF "$a2"="" 476 _M_PREIND $i$a3, "$r", $a0, $a1 477 ELSE 478 _M_PREIND $i$a3, "$r", $a0, "$a1,$a2" 479 ENDIF 480 ENDIF 481 ENDIF 482 ELSE 483 LCLA _Offset 484 _Offset SETA _Workspace + $a0$_F 485 ASSERT (_Offset:AND:($a-1))=0 486 $i$a1 $r, [sp, #_Offset] 487 ENDIF 488 MEND 489 490 ;// Handle post indexed load/stores 491 ;// op reg, [base], offset 492 MACRO 493 _M_POSTIND $i,$r,$a0,$a1 494 LCLS _base 495 LCLS _offset 496 IF {CONFIG}=16 ;// Thumb 497 _base SETS ("$a0":LEFT:(:LEN:"$a0"-1)):RIGHT:(:LEN:"$a0"-2) ;// remove [] 498 _offset SETS "$a1" 499 IF _offset:LEFT:1="+" 500 _offset SETS _offset:RIGHT:(:LEN:_offset-1) 501 ENDIF 502 $i $r, $a0 503 IF _offset:LEFT:1="-" 504 _offset SETS _offset:RIGHT:(:LEN:_offset-1) 505 SUB $_base, $_base, $_offset 506 ELSE 507 ADD $_base, $_base, $_offset 508 ENDIF 509 ELSE ;// ARM 510 $i $r, $a0, $a1 511 ENDIF 512 MEND 513 514 ;// Handle pre indexed load/store 515 ;// op reg, [base, offset]{!} 516 MACRO 517 _M_PREIND $i,$r,$a0,$a1 518 LCLS _base 519 LCLS _offset 520 IF ({CONFIG}=16):LAND:(("$a1":RIGHT:2)="]!") 521 _base SETS "$a0":RIGHT:(:LEN:("$a0")-1) 522 _offset SETS "$a1":LEFT:(:LEN:("$a1")-2) 523 $i $r, [$_base, $_offset] 524 ADD $_base, $_base, $_offset 525 ELSE 526 $i $r, $a0, $a1 527 ENDIF 528 MEND 529 530 ;// Load unsigned byte from stack 531 MACRO 532 M_LDRB $r,$a0,$a1,$a2,$a3 533 _M_DATA "LDRB",1,$r,$a0,$a1,$a2,$a3 534 MEND 535 536 ;// Load signed byte from stack 537 MACRO 538 M_LDRSB $r,$a0,$a1,$a2,$a3 539 _M_DATA "LDRSB",1,$r,$a0,$a1,$a2,$a3 540 MEND 541 542 ;// Store byte to stack 543 MACRO 544 M_STRB $r,$a0,$a1,$a2,$a3 545 _M_DATA "STRB",1,$r,$a0,$a1,$a2,$a3 546 MEND 547 548 ;// Load unsigned half word from stack 549 MACRO 550 M_LDRH $r,$a0,$a1,$a2,$a3 551 _M_DATA "LDRH",2,$r,$a0,$a1,$a2,$a3 552 MEND 553 554 ;// Load signed half word from stack 555 MACRO 556 M_LDRSH $r,$a0,$a1,$a2,$a3 557 _M_DATA "LDRSH",2,$r,$a0,$a1,$a2,$a3 558 MEND 559 560 ;// Store half word to stack 561 MACRO 562 M_STRH $r,$a0,$a1,$a2,$a3 563 _M_DATA "STRH",2,$r,$a0,$a1,$a2,$a3 564 MEND 565 566 ;// Load word from stack 567 MACRO 568 M_LDR $r,$a0,$a1,$a2,$a3 569 _M_DATA "LDR",4,$r,$a0,$a1,$a2,$a3 570 MEND 571 572 ;// Store word to stack 573 MACRO 574 M_STR $r,$a0,$a1,$a2,$a3 575 _M_DATA "STR",4,$r,$a0,$a1,$a2,$a3 576 MEND 577 578 ;// Load double word from stack 579 MACRO 580 M_LDRD $r0,$r1,$a0,$a1,$a2,$a3 581 _M_DATA "LDRD",8,"$r0,$r1",$a0,$a1,$a2,$a3 582 MEND 583 584 ;// Store double word to stack 585 MACRO 586 M_STRD $r0,$r1,$a0,$a1,$a2,$a3 587 _M_DATA "STRD",8,"$r0,$r1",$a0,$a1,$a2,$a3 588 MEND 589 590 ;// Get absolute address of stack allocated location 591 MACRO 592 M_ADR $a, $b, $cc 593 _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F) 594 MEND 595 596 ;// Get absolute address of stack allocated location and align the address to 16 bytes 597 MACRO 598 M_ADR16 $a, $b, $cc 599 _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F$_16) 600 601 ;// Now align $a to 16 bytes 602 BIC$cc $a,$a,#0x0F 603 MEND 604 605 ;// Get absolute address of stack allocated location and align the address to 32 bytes 606 MACRO 607 M_ADR32 $a, $b, $cc 608 _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F$_32) 609 610 ;// Now align $a to 32 bytes 611 BIC$cc $a,$a,#0x1F 612 MEND 613 614 ;////////////////////////////////////////////////////////// 615 ;// Function header and footer macros 616 ;////////////////////////////////////////////////////////// 617 618 ;// Function Header Macro 619 ;// Generates the function prologue 620 ;// Note that functions should all be "stack-moves-once" 621 ;// The FNSTART and FNEND macros should be the only places 622 ;// where the stack moves. 623 ;// 624 ;// $name = function name 625 ;// $rreg = "" don't stack any registers 626 ;// "lr" stack "lr" only 627 ;// "rN" stack registers "r4-rN,lr" 628 ;// $dreg = "" don't stack any D registers 629 ;// "dN" stack registers "d8-dN" 630 ;// 631 ;// Note: ARM Archicture procedure call standard AAPCS 632 ;// states that r4-r11, sp, d8-d15 must be preserved by 633 ;// a compliant function. 634 MACRO 635 M_START $name, $rreg, $dreg 636 ASSERT :LNOT:_InFunc 637 ASSERT "$name"!="" 638 _InFunc SETL {TRUE} 639 _RBytes SETA 0 640 _Workspace SETA 0 641 642 ;// Create an area for the function 643 AREA |.text|, CODE 644 EXPORT $name 645 $name FUNCTION 646 647 ;// Save R registers 648 _M_GETRREGLIST $rreg 649 IF _RRegList<>"" 650 STMFD sp!, {$_RRegList, lr} 651 ENDIF 652 653 ;// Save D registers 654 _M_GETDREGLIST $dreg 655 IF _DRegList<>"" 656 VSTMFD sp!, {$_DRegList} 657 ENDIF 658 659 660 ;// Ensure size claimed on stack is 8-byte aligned 661 IF ((_SBytes:AND:7)!=0) 662 _SBytes SETA _SBytes + (8 - (_SBytes:AND:7)) 663 ENDIF 664 665 IF (_SBytes!=0) 666 _M_OPC SUB, sp, sp, _SBytes 667 ENDIF 668 669 670 _ABytes SETA _SBytes + _RBytes - _Workspace 671 672 673 ;// Print function name if debug enabled 674 M_PRINTF "$name\n", 675 MEND 676 677 ;// Work out a list of R saved registers 678 MACRO 679 _M_GETRREGLIST $rreg 680 IF "$rreg"="" 681 _RRegList SETS "" 682 MEXIT 683 ENDIF 684 IF "$rreg"="lr":LOR:"$rreg"="r4" 685 _RRegList SETS "r4" 686 _RBytes SETA _RBytes+8 687 MEXIT 688 ENDIF 689 IF "$rreg"="r5":LOR:"$rreg"="r6" 690 _RRegList SETS "r4-r6" 691 _RBytes SETA _RBytes+16 692 MEXIT 693 ENDIF 694 IF "$rreg"="r7":LOR:"$rreg"="r8" 695 _RRegList SETS "r4-r8" 696 _RBytes SETA _RBytes+24 697 MEXIT 698 ENDIF 699 IF "$rreg"="r9":LOR:"$rreg"="r10" 700 _RRegList SETS "r4-r10" 701 _RBytes SETA _RBytes+32 702 MEXIT 703 ENDIF 704 IF "$rreg"="r11":LOR:"$rreg"="r12" 705 _RRegList SETS "r4-r12" 706 _RBytes SETA _RBytes+40 707 MEXIT 708 ENDIF 709 INFO 1, "Unrecognized saved r register limit '$rreg'" 710 MEND 711 712 ;// Work out a list of D saved registers 713 MACRO 714 _M_GETDREGLIST $dreg 715 IF "$dreg"="" 716 _DRegList SETS "" 717 MEXIT 718 ENDIF 719 IF "$dreg"="d8" 720 _DRegList SETS "d8" 721 _RBytes SETA _RBytes+8 722 MEXIT 723 ENDIF 724 IF "$dreg"="d9" 725 _DRegList SETS "d8-d9" 726 _RBytes SETA _RBytes+16 727 MEXIT 728 ENDIF 729 IF "$dreg"="d10" 730 _DRegList SETS "d8-d10" 731 _RBytes SETA _RBytes+24 732 MEXIT 733 ENDIF 734 IF "$dreg"="d11" 735 _DRegList SETS "d8-d11" 736 _RBytes SETA _RBytes+32 737 MEXIT 738 ENDIF 739 IF "$dreg"="d12" 740 _DRegList SETS "d8-d12" 741 _RBytes SETA _RBytes+40 742 MEXIT 743 ENDIF 744 IF "$dreg"="d13" 745 _DRegList SETS "d8-d13" 746 _RBytes SETA _RBytes+48 747 MEXIT 748 ENDIF 749 IF "$dreg"="d14" 750 _DRegList SETS "d8-d14" 751 _RBytes SETA _RBytes+56 752 MEXIT 753 ENDIF 754 IF "$dreg"="d15" 755 _DRegList SETS "d8-d15" 756 _RBytes SETA _RBytes+64 757 MEXIT 758 ENDIF 759 INFO 1, "Unrecognized saved d register limit '$dreg'" 760 MEND 761 762 ;// Produce function return instructions 763 MACRO 764 _M_RET $cc 765 IF _DRegList<>"" 766 VPOP$cc {$_DRegList} 767 ENDIF 768 IF _RRegList="" 769 BX$cc lr 770 ELSE 771 LDM$cc.FD sp!, {$_RRegList, pc} 772 ENDIF 773 MEND 774 775 ;// Early Function Exit Macro 776 ;// $cc = condition to exit with 777 ;// (Example: M_EXIT EQ) 778 MACRO 779 M_EXIT $cc 780 ASSERT _InFunc 781 IF _SBytes!=0 782 ;// Restore stack frame and exit 783 B$cc _End$_F 784 ELSE 785 ;// Can return directly 786 _M_RET $cc 787 ENDIF 788 MEND 789 790 ;// Function Footer Macro 791 ;// Generates the function epilogue 792 MACRO 793 M_END 794 ASSERT _InFunc 795 _InFunc SETL {FALSE} 796 _End$_F 797 798 ;// Restore the stack pointer to its original value on function entry 799 IF _SBytes!=0 800 _M_OPC ADD, sp, sp, _SBytes 801 ENDIF 802 _M_RET 803 ENDFUNC 804 805 ;// Reset the global stack tracking variables back to their 806 ;// initial values, and increment the function count 807 _SBytes SETA 0 808 _F SETA _F+1 809 MEND 810 811 812 ;//========================================================================== 813 ;// Debug Macros 814 ;//========================================================================== 815 816 GBLL DEBUG_ON 817 DEBUG_ON SETL {FALSE} 818 GBLL DEBUG_STALLS_ON 819 DEBUG_STALLS_ON SETL {FALSE} 820 821 ;//========================================================================== 822 ;// Debug call to printf 823 ;// M_PRINTF $format, $val0, $val1, $val2 824 ;// 825 ;// Examples: 826 ;// M_PRINTF "x=%08x\n", r0 827 ;// 828 ;// This macro preserves the value of all registers including the 829 ;// flags. 830 ;//========================================================================== 831 832 MACRO 833 M_PRINTF $format, $val0, $val1, $val2 834 IF DEBUG_ON 835 836 IMPORT printf 837 LCLA nArgs 838 nArgs SETA 0 839 840 ;// save registers so we don't corrupt them 841 STMFD sp!, {r0-r12, lr} 842 843 ;// Drop stack to give us some workspace 844 SUB sp, sp, #16 845 846 ;// Save registers we need to print to the stack 847 IF "$val2" <> "" 848 ASSERT "$val1" <> "" 849 STR $val2, [sp, #8] 850 nArgs SETA nArgs+1 851 ENDIF 852 IF "$val1" <> "" 853 ASSERT "$val0" <> "" 854 STR $val1, [sp, #4] 855 nArgs SETA nArgs+1 856 ENDIF 857 IF "$val0"<>"" 858 STR $val0, [sp] 859 nArgs SETA nArgs+1 860 ENDIF 861 862 ;// Now we are safe to corrupt registers 863 ADR r0, %FT00 864 IF nArgs=1 865 LDR r1, [sp] 866 ENDIF 867 IF nArgs=2 868 LDMIA sp, {r1,r2} 869 ENDIF 870 IF nArgs=3 871 LDMIA sp, {r1,r2,r3} 872 ENDIF 873 874 ;// print the values 875 MRS r4, cpsr ;// preserve flags 876 BL printf 877 MSR cpsr_f, r4 ;// restore flags 878 B %FT01 879 00 ;// string to print 880 DCB "$format", 0 881 ALIGN 882 01 ;// Finished 883 ADD sp, sp, #16 884 ;// Restore registers 885 LDMFD sp!, {r0-r12,lr} 886 887 ENDIF ;// DEBUG_ON 888 MEND 889 890 891 ;// Stall Simulation Macro 892 ;// Inserts a given number of NOPs for the currently 893 ;// defined platform 894 MACRO 895 M_STALL $plat1stall, $plat2stall, $plat3stall, $plat4stall, $plat5stall, $plat6stall 896 IF DEBUG_STALLS_ON 897 _M_STALL_SUB $plat1stall 898 _M_STALL_SUB $plat2stall 899 _M_STALL_SUB $plat3stall 900 _M_STALL_SUB $plat4stall 901 _M_STALL_SUB $plat5stall 902 _M_STALL_SUB $plat6stall 903 ENDIF 904 MEND 905 906 MACRO 907 _M_STALL_SUB $platstall 908 IF "$platstall"!="" 909 LCLA _pllen 910 LCLS _pl 911 LCLL _pllog 912 _pllen SETA :LEN:"$platstall" 913 _pl SETS "$platstall":LEFT:(_pllen - 2) 914 IF :DEF:$_pl 915 IF $_pl 916 LCLS _st 917 LCLA _stnum 918 _st SETS "$platstall":RIGHT:1 919 _stnum SETA $_st 920 WHILE _stnum>0 921 MOV sp, sp 922 _stnum SETA _stnum - 1 923 WEND 924 ENDIF 925 ENDIF 926 ENDIF 927 MEND 928 929 930 931 ;//========================================================================== 932 ;// Endian Invarience Macros 933 ;// 934 ;// The idea behind these macros is that if an array is 935 ;// loaded as words then the SMUL00 macro will multiply 936 ;// array elements 0 regardless of the endianess of the 937 ;// system. For little endian SMUL00=SMULBB, for big 938 ;// endian SMUL00=SMULTT and similarly for other packed operations. 939 ;// 940 ;//========================================================================== 941 942 MACRO 943 LIBI4 $comli, $combi, $a, $b, $c, $d, $cc 944 IF {ENDIAN}="big" 945 $combi.$cc $a, $b, $c, $d 946 ELSE 947 $comli.$cc $a, $b, $c, $d 948 ENDIF 949 MEND 950 951 MACRO 952 LIBI3 $comli, $combi, $a, $b, $c, $cc 953 IF {ENDIAN}="big" 954 $combi.$cc $a, $b, $c 955 ELSE 956 $comli.$cc $a, $b, $c 957 ENDIF 958 MEND 959 960 ;// SMLAxy macros 961 962 MACRO 963 SMLA00 $a, $b, $c, $d, $cc 964 LIBI4 SMLABB, SMLATT, $a, $b, $c, $d, $cc 965 MEND 966 967 MACRO 968 SMLA01 $a, $b, $c, $d, $cc 969 LIBI4 SMLABT, SMLATB, $a, $b, $c, $d, $cc 970 MEND 971 972 MACRO 973 SMLA0B $a, $b, $c, $d, $cc 974 LIBI4 SMLABB, SMLATB, $a, $b, $c, $d, $cc 975 MEND 976 977 MACRO 978 SMLA0T $a, $b, $c, $d, $cc 979 LIBI4 SMLABT, SMLATT, $a, $b, $c, $d, $cc 980 MEND 981 982 MACRO 983 SMLA10 $a, $b, $c, $d, $cc 984 LIBI4 SMLATB, SMLABT, $a, $b, $c, $d, $cc 985 MEND 986 987 MACRO 988 SMLA11 $a, $b, $c, $d, $cc 989 LIBI4 SMLATT, SMLABB, $a, $b, $c, $d, $cc 990 MEND 991 992 MACRO 993 SMLA1B $a, $b, $c, $d, $cc 994 LIBI4 SMLATB, SMLABB, $a, $b, $c, $d, $cc 995 MEND 996 997 MACRO 998 SMLA1T $a, $b, $c, $d, $cc 999 LIBI4 SMLATT, SMLABT, $a, $b, $c, $d, $cc 1000 MEND 1001 1002 MACRO 1003 SMLAB0 $a, $b, $c, $d, $cc 1004 LIBI4 SMLABB, SMLABT, $a, $b, $c, $d, $cc 1005 MEND 1006 1007 MACRO 1008 SMLAB1 $a, $b, $c, $d, $cc 1009 LIBI4 SMLABT, SMLABB, $a, $b, $c, $d, $cc 1010 MEND 1011 1012 MACRO 1013 SMLAT0 $a, $b, $c, $d, $cc 1014 LIBI4 SMLATB, SMLATT, $a, $b, $c, $d, $cc 1015 MEND 1016 1017 MACRO 1018 SMLAT1 $a, $b, $c, $d, $cc 1019 LIBI4 SMLATT, SMLATB, $a, $b, $c, $d, $cc 1020 MEND 1021 1022 ;// SMULxy macros 1023 1024 MACRO 1025 SMUL00 $a, $b, $c, $cc 1026 LIBI3 SMULBB, SMULTT, $a, $b, $c, $cc 1027 MEND 1028 1029 MACRO 1030 SMUL01 $a, $b, $c, $cc 1031 LIBI3 SMULBT, SMULTB, $a, $b, $c, $cc 1032 MEND 1033 1034 MACRO 1035 SMUL0B $a, $b, $c, $cc 1036 LIBI3 SMULBB, SMULTB, $a, $b, $c, $cc 1037 MEND 1038 1039 MACRO 1040 SMUL0T $a, $b, $c, $cc 1041 LIBI3 SMULBT, SMULTT, $a, $b, $c, $cc 1042 MEND 1043 1044 MACRO 1045 SMUL10 $a, $b, $c, $cc 1046 LIBI3 SMULTB, SMULBT, $a, $b, $c, $cc 1047 MEND 1048 1049 MACRO 1050 SMUL11 $a, $b, $c, $cc 1051 LIBI3 SMULTT, SMULBB, $a, $b, $c, $cc 1052 MEND 1053 1054 MACRO 1055 SMUL1B $a, $b, $c, $cc 1056 LIBI3 SMULTB, SMULBB, $a, $b, $c, $cc 1057 MEND 1058 1059 MACRO 1060 SMUL1T $a, $b, $c, $cc 1061 LIBI3 SMULTT, SMULBT, $a, $b, $c, $cc 1062 MEND 1063 1064 MACRO 1065 SMULB0 $a, $b, $c, $cc 1066 LIBI3 SMULBB, SMULBT, $a, $b, $c, $cc 1067 MEND 1068 1069 MACRO 1070 SMULB1 $a, $b, $c, $cc 1071 LIBI3 SMULBT, SMULBB, $a, $b, $c, $cc 1072 MEND 1073 1074 MACRO 1075 SMULT0 $a, $b, $c, $cc 1076 LIBI3 SMULTB, SMULTT, $a, $b, $c, $cc 1077 MEND 1078 1079 MACRO 1080 SMULT1 $a, $b, $c, $cc 1081 LIBI3 SMULTT, SMULTB, $a, $b, $c, $cc 1082 MEND 1083 1084 ;// SMLAWx, SMULWx macros 1085 1086 MACRO 1087 SMLAW0 $a, $b, $c, $d, $cc 1088 LIBI4 SMLAWB, SMLAWT, $a, $b, $c, $d, $cc 1089 MEND 1090 1091 MACRO 1092 SMLAW1 $a, $b, $c, $d, $cc 1093 LIBI4 SMLAWT, SMLAWB, $a, $b, $c, $d, $cc 1094 MEND 1095 1096 MACRO 1097 SMULW0 $a, $b, $c, $cc 1098 LIBI3 SMULWB, SMULWT, $a, $b, $c, $cc 1099 MEND 1100 1101 MACRO 1102 SMULW1 $a, $b, $c, $cc 1103 LIBI3 SMULWT, SMULWB, $a, $b, $c, $cc 1104 MEND 1105 1106 ;// SMLALxy macros 1107 1108 1109 MACRO 1110 SMLAL00 $a, $b, $c, $d, $cc 1111 LIBI4 SMLALBB, SMLALTT, $a, $b, $c, $d, $cc 1112 MEND 1113 1114 MACRO 1115 SMLAL01 $a, $b, $c, $d, $cc 1116 LIBI4 SMLALBT, SMLALTB, $a, $b, $c, $d, $cc 1117 MEND 1118 1119 MACRO 1120 SMLAL0B $a, $b, $c, $d, $cc 1121 LIBI4 SMLALBB, SMLALTB, $a, $b, $c, $d, $cc 1122 MEND 1123 1124 MACRO 1125 SMLAL0T $a, $b, $c, $d, $cc 1126 LIBI4 SMLALBT, SMLALTT, $a, $b, $c, $d, $cc 1127 MEND 1128 1129 MACRO 1130 SMLAL10 $a, $b, $c, $d, $cc 1131 LIBI4 SMLALTB, SMLALBT, $a, $b, $c, $d, $cc 1132 MEND 1133 1134 MACRO 1135 SMLAL11 $a, $b, $c, $d, $cc 1136 LIBI4 SMLALTT, SMLALBB, $a, $b, $c, $d, $cc 1137 MEND 1138 1139 MACRO 1140 SMLAL1B $a, $b, $c, $d, $cc 1141 LIBI4 SMLALTB, SMLALBB, $a, $b, $c, $d, $cc 1142 MEND 1143 1144 MACRO 1145 SMLAL1T $a, $b, $c, $d, $cc 1146 LIBI4 SMLALTT, SMLALBT, $a, $b, $c, $d, $cc 1147 MEND 1148 1149 MACRO 1150 SMLALB0 $a, $b, $c, $d, $cc 1151 LIBI4 SMLALBB, SMLALBT, $a, $b, $c, $d, $cc 1152 MEND 1153 1154 MACRO 1155 SMLALB1 $a, $b, $c, $d, $cc 1156 LIBI4 SMLALBT, SMLALBB, $a, $b, $c, $d, $cc 1157 MEND 1158 1159 MACRO 1160 SMLALT0 $a, $b, $c, $d, $cc 1161 LIBI4 SMLALTB, SMLALTT, $a, $b, $c, $d, $cc 1162 MEND 1163 1164 MACRO 1165 SMLALT1 $a, $b, $c, $d, $cc 1166 LIBI4 SMLALTT, SMLALTB, $a, $b, $c, $d, $cc 1167 MEND 1168 1169 ENDIF ;// ARMCOMM_S_H 1170 1171 END 1172