8 STRUCTURED CONTROL STATEMENTS

This chapter contains the following sections:

Introduction
Structured Control Directives
Syntax
.BREAK Statement
.CONTINUE Statement
.FOR Statement
.IF Statement
.LOOP Statement
.REPEAT Statement
.WHILE Statement
Simple and Compound Expressions
Simple Expressions
Condition Code Expressions
Operand Comparison Expressions
Compound Expressions
Statement Formatting
Expression Formatting
.FOR/.LOOP Formatting
Assembly Lising Format
Effects on the Programmer's Environment

8.1 Introduction

An assembly language provides an instruction set for performing certain rudimentary operations. These operations in turn may be combined into control structures such as loops (FOR, REPEAT, WHILE) or conditional branches (IF-THEN, IF-THEN-ELSE). The assembler, however, accepts formal, high-level directives that specify these control structures, generating the appropriate assembly language instructions for their efficient implementation. This use of structured control statement directives improves the readability of assembly language programs, without compromising the desirable aspects of programming in an assembly language.

8.2 Structured Control Directives

The following directives are used for structured control. Note the leading period, which distinguishes these keywords from other directives and mnemonics. Structured control directives may be specified in either upper or lower case, but they must appear in the opcode field of the instruction line (e.g. they must be preceded either by a label, a space, or a tab).

In addition, the following keywords are used in structured control statements:

AND, DO, and OR are reserved assembler instruction mnemonics.

8.3 S yntax

The formats for the .BREAK, .CONTINUE, .FOR, .IF, .LOOP, .REPEAT, and .WHILE statements are given in the following sub-sections. Syntactic variables used in the formats are defined as follows:

expression A simple or compound expression (section 8.4).

stmtlist Zero or more assembler directives, structured control statements, or executable instructions.

Note that an assembler directive (Chapter 7 ) occurring within a structured control statement is examined exactly once -- at assembly time. Thus the presence of a directive within a .FOR, .LOOP, .REPEAT, or .WHILE statement does not imply repeated occurrence of an assembler directive; nor does the presence of a directive within an .IF-THEN-.ELSE structured control statement imply conditional assembly.

op1 A user-defined operand whose register/memory location holds the .FOR loop counter. The effective address must use a memory alterable addressing mode (e.g. it cannot be an immediate value).

op2 The initial value of the .FOR loop counter. The effective address may be any mode, and may represent an arbitrary assembler expression (Section 5.2, Expressions).

op3 The terminating value of the .FOR loop counter. The effective address may be any mode, and may represent an arbitrary assembler expression (Section 5.2 , Expressions).

op4 The step (increment/decrement) of the .FOR loop counter each time through the loop. If not specified, it defaults to a value of #1. The effective address may be any mode, and may represent an arbitrary assembler expression (Section 5.2, Expressions).

cnt The terminating value in a .LOOP statement. This can be any arbitrary assembler expression (Section 5.2 , Expressions).

All structured control statements may be followed by normal assembler comments on the same logical line.

8.3.1 .BREAK Statement

Syntax:

.BREAK

Function:

The .BREAK statement causes an immediate exit from the innermost enclosing loop construct (.WHILE, .REPEAT, .FOR, .LOOP).

A .BREAK statement does not exit an .IF-THEN-.ELSE construct. If a .BREAK is encountered with no loop statement active, a warning is issued.

.BREAK should be used with care near .ENDL directives or near the end of DO loops. It generates a jump instruction which is illegal in those contexts.

Examples:

.WHILE  x:(r1)+ <GT> #0  ;loop until zero is found
  .
  .
  .
.IF  <cs>  ;carry set?
.BREAK    ;causes exit from WHILE loop
.ENDI
  .
  .  ;any instructions here are skipped
  .
.ENDW
;execution resumes here after .BREAK

8.3.2 .CONTINUE Statement

Syntax:

.CONTINUE

Function:

The .CONTINUE statement causes the next iteration of a looping construct (.WHILE, .REPEAT, .FOR, .LOOP) to begin. This means that the loop expression or operand comparison is performed immediately, bypassing any subsequent instructions.

If a .CONTINUE is encountered with no loop statement active, a warning is issued.

.CONTINUE should be used with care near .ENDL directives or near the end of DO loops. It generates a jump instruction which is illegal in those contexts.

One or more .CONTINUE directives inside a .LOOP construct will generate a NOP instruction just before the loop address.

Examples:

.REPEAT
  .
  .
  .
.IF  <cs>  ;carry set?
.CONTINUE  ;causes immediate jump to .UNTIL
.ENDI
  .
  .  ;any instructions here are skipped
  .
.UNTIL  x:(r1)+ <EQ> #0  ;evaluation here after
          ;.CONTINUE

8.3.3 .FOR Statement

Syntax:

.FOR op1 = op2 {TO | DOWNTO} op3 [BY op4] [DO]

stmtlist

.ENDF

Function:

Initialize op1 to op2 and perform stmtlist until op1 is greater (TO) or less than (DOWNTO) op3. Makes use of a user-defined operand, op1, to serve as a loop counter. .FOR-TO allows counting upward, while .FOR-DOWNTO allows counting downward. The programmer may specify an increment/decrement step size in op4, or select the default step size of #1 by omitting the BY clause. A .FOR-TO loop is not executed if op2 is greater than op3 upon entry to the loop. Similarly, a .FOR-DOWNTO loop is not executed if op2 is less then op3.

op1 must be a writable register or memory location. It is initialized at the beginning of the loop, and updated at each pass through the loop. Any immediate operands must be preceded by a pound sign (#). Memory references must be preceded by a memory space qualifier (X:, Y:, or P:). L memory references are not allowed. Operands must be or refer to single-word values.

The logic generated by the .FOR directive makes use of several DSP data registers (A, X0, Y0, Y1). In fact, two data registers are used to hold the step and target values, respectively, throughout the loop; they are never reloaded by the generated code. It is recommended that these registers not be used within the body of the loop, or that they be saved and restored prior to loop evaluation.

The DO keyword is optional.

Examples:

.FOR  X:CNT = #0 TO Y:(targ*2)+114  ;loop on X:CNT
  .
  .
  .
.ENDF

8.3.4 .IF Statement

Syntax:

.IF expression [THEN]
stmtlist
[.ELSE
stmtlist]
.ENDI

Function:

If expression is true, execute stmtlist following THEN (the keyword THEN is optional); if expression is false, execute stmtlist following .ELSE, if present; otherwise, advance to the instruction following .ENDI.

In the case of nested .IF-THEN-.ELSE statements, each .ELSE refers to the most recent .IF-THEN sequence.

Examples:

.IF  <EQ>    ; zero bit set?
  .
  .
  .
.ENDI

8.3.5 .LOOP Statement

Syntax:

.LOOP cnt
stmtlist
.ENDL

Function:

Execute stmtlist cnt times. this is similar to the .FOR loop construct, except that the initial counter and step value are implied to be #1. It is actually a shorthand method for setting up a hardware DO loop on the DSP, without having to worry about addressing modes or label placement.

Since the .LOOP statement generates instructions for a hardware DO loop, the same restrictions apply as to the use of certain instructions near the end of the loop, nesting restrictions, etc.

One or more .CONTINUE directives inside a .LOOP construct will generate a NOP instruction just before the loop address.

Examples:

.LOOP    LPCNT    ;hardware loop LPCNT times
  .
  .
  .
.ENDL

8.3.6 .REPEAT Statement

Syntax:

.REPEAT
stmtlist
.UNTIL expression

Function:

stmtlist is executed repeatedly until expression is true. When expression becomes true, advance to the next instruction following .UNTIL.

The stmtlist is executed at least once, even if expression is true upon entry to the .REPEAT loop.

Examples:

.REPEAT
  .
  .
  .
.UNTIL  x:(r1)+ <EQ> #0  ;loop until zero is found

8.3.7 .WHILE Statement

Syntax:

.WHILE expression [DO]

stmtlist

.ENDW

Function:

The expression is tested before execution of stmtlist. While expression remains true, stmtlist is executed repeatedly. When expression evaluates false, advance to the instruction following the .ENDW statement.

If expression is false upon entry to the .WHILE loop, stmtlist is not executed; execution continues after the .ENDW directive.

The DO keyword is optional.

Examples:

.WHILE  x:(r1)+ <GT> #0   ;loop until zero is found
  .
  .
  .
.ENDW

8.4 Simple and Compound Expressions

Expressions are an integral part of .IF, .REPEAT, and .WHILE statements. Structured control statement expressions should not be confused with the assembler expressions discussed in section 5.2 , Expressions. The latter are evaluated at assembly time and will be referred to here as "assembler expressions"; they can serve as operands in structured control statement expressions. The structured control statement expressions described below are evaluated at run-time and will be referred to in the following discussion simply as "expressions".

A structured control statement expression may be simple or compound. A compound expression consists of two or more simple expressions joined by either AND or OR (but not both in a single compound expression).

8.4.1 Simple Expressions

Simple expressions are concerned with the bits of the Condition Code Register (CCR). These expressions are of two types. The first type merely tests conditions currently specified by the contents of the CCR (section 8.4.1.1). The second type sets up a comparison of two operands to set the condition codes, and afterwards tests the codes (section 8.4.1.2).

8.4.1.1 Condition Code Expressions

A variety of tests (identical to those in the Jcc instruction) may be performed, based on the CCR condition codes. The condition codes, in this case, are preset by either a user-generated instruction or a structured operand-comparison expression (section 8.4.1.2 ). Each test is expressed in the structured control statement by a mnemonic enclosed in angle brackets.

The following condition code mnemonics can be used:

When processed by the assembler, the expression generates an inverse conditional jump to beyond the matching .ENDx/.UNTIL directive. For example:

  .IF  <EQ>  ;zero bit set?
+  bne  Z_L00002  ;code generated by assembler
  CLR  D1  ;user code
  .ENDI
+  Z_L00002    ;assembler-generated label
  .REPEAT    ;subtract until D0 < D7
+  Z_L00034    ;assembler-generated label
  SUB  D7,D0  ;user code
  .UNTIL  <LT>
+  bge  Z_L00034  ;code generated by assembler

8.4.1.2 Operand Comparison Expressions

Two operands may be compared in a simple expression, with subsequent transfer of control based on that comparison. Such a comparison takes the form:

where cc is a condition mnemonic enclosed in angle brackets (as described in section 8.4.1.1), and op1 and op2 are register or memory references, symbols, or assembler expressions. When processed by the assembler, the operands are arranged such that a compare/jump sequence of the following form always results:

where the jump conditional is the inverse of cc. Ordinarily op1 is moved to the reg1 data register and op2 is moved to the reg2 data register prior to the compare. This is not always the case, however: if op1 happens to be reg2 and op2 is reg1, an intermediate register is used as a scratch register. In any event, worst case code generation for a given operand comparison expression is generally two moves, a compare, and a conditional jump.

Jumps or branches generated by structured control statements are forced long because the number and address of intervening instructions between a control statement and its termination are not known by the assembler. The programmer may circumvent this behavior by use of the SCSJMP directive (see Chapter 7 ).

Any immediate operands must be preceded by a pound sign (#). Memory references must be preceded by a memory space qualifier (X:, Y:, or P:). L memory references are not allowed. Operands must be or refer to single-word values.

Note that values in the reg1 and reg2 data registers are not saved before expression evaluation. This means that any user data in those registers will be overwritten each time the expression is evaluated at runtime. The programmer should take care either to save needed contents of the registers, reassign data registers using the SCSREG directive, or not use them at all in the body of the particular structured construct being executed. The data registers used by the structured control statements are A, X0, Y0 and Y1.

8.4.2 Compound Expressions

A compound expression consists of two or more simple expressions (section 8.4.1) joined by a logical operator (AND or OR). The boolean value of the compound expression is determined by the boolean values of the simple expressions and the nature of the logical operator. Note that the result of mixing logical operators in a compound expression is undefined:

The simple expressions are evaluated left to right. Note that this means the result of one simple expression could have an impact on the result of subsequent simple expression, because of the condition code settings stemming from the assembler-generated compare.

If the compound expression is an AND expression and one of the simple expressions is found to be false, any further simple expressions are not evaluated. Likewise, if the compound expression is an OR expression and one of the simple expressions is found to be true, any further simple expressions are not evaluated. In these cases, the compound expression is either false or true, respectively, and the condition codes reflects the result of the last simple expression evaluated.

8.5 Statement Formatting

The format of structured control statements differs somewhat from normal assembler usage. Whereas a standard assembler line is split into fields separated by blanks or tabs, with no white space inside the fields, structured control statement formats vary depending on the statement being analyzed. In general, all structured control directives are placed in the opcode field (with an optional label in the label field) and white space separates all distinct fields in the statement. Any structured control statement may be followed by a comment on the same logical line.

8.5.1 Expression Formatting

Given an expression of the form:

there must be white space (blank, tab) between all operands and their associated operators, including boolean operators in compound expressions. Moreover, there must be white space between the structured control directive and the expression, and between the expression and any optional directive modifier (THEN, DO). An assembler expression (section 5.2, Expressions) used as an operand in a structured control statement expression must not have white space in it, since it is parsed by the standard assembler evaluation routines:

8.5.2 .FOR/.LOOP Formatting

The .FOR and .LOOP directives represent special cases. The .FOR structured control statement consists of several fields:

There must be white space between all operands and other syntactic entities such as =, TO, BY, and DO. As with expression formatting, an assembler expression used as an operand must not have white space in it:

In the example above, the .FOR loop operands represented as assembler expressions (symbol, function) do not have embedded white space, whereas the loop operands are always separated from structured control statement keywords by white space.

The count field of a .LOOP statement must be separated from the .LOOP directive by white space. The count itself may be any arbitrary assembler expression, and therefore must not contain embedded blanks.

8.5.3 Assembly Listing Format

Structured control statements begin with the directive in the opcode field; any optional label is output in the label field. The rest of the statement is left as is in the operand field, except for any trailing comment; the X and Y data movement fields are ignored. Comments following the statement are output in the comment field (see Chapter 4 ).

Statements are expanded using the macro facilities of the assembler. Thus the generated code can be sent to the listing by specifying the MEX assembler option, via the OPT directive (Chapter 7 ).

8.6 Effects on the Programmer's Environment

During assembly, global labels beginning with "Z_L" are generated. They are stored in the symbol table and should not be duplicated in user-defined labels. These non-local labels ordinarily are not visible to the programmer, but there can be problems when local (underscore) labels are interspersed among structured control statements. The SCL option (see the OPT directive, Chapter 7 ) causes the assembler to maintain the current local label scope when a structured control statement label is encountered.

In the .FOR loop, op1 is a user-defined symbol. When exiting the loop, the memory/register assigned to this symbol contains the value which caused the exit from the loop.

A compare instruction is produced by the assembler whenever two operands are tested in a structured statement. At runtime, these assembler-generated instructions set the condition codes of the CCR (in the case of a loop, the condition codes are set repeatedly). Any user-written code either within or following a structured statement that references CCR directly (move) or indirectly (conditional) jump/transfer) should be attentive to the effect of these instructions.

Jumps or branches generated by structured control statements are forced long because the number and address of intervening instructions between a control statement and its termination are not known by the assembler. The programmer may circumvent this behavior by use of the SCSJMP directive (see Chapter 7 ).

In all structured control statements except those using only a single condition code expression, registers are used to set up the required counters and comparands. In some cases, these registers are effectively reserved; the .FOR loop uses two data registers to hold the step and target values, respectively, and performs no save/restore operations on these registers. The assembler, in fact, does no save/restore processing in any structured control operation; it simply moves the operands into appropriate registers to execute the compare. The following registers are used by the assembler in support of structured control statements:

The SCSREG directive (Chapter 7 ) may be used to reassign structured control statement registers. The MEX assembler option (see the OPT directive, Chapter 7 ) may be used to send the assembler-generated code to the listing file for examination of possible register use conflicts.


Copyright © 2002 Altium BV