Overview of Jump Statements in SINUMERIK NC Programming
The SINUMERIK 840D sl, SINUMERIK 828D, and SINUMERIK ONE controllers expose three related jump statements for unstructured control flow inside an NC program: GOTOF, GOTOB, and GOTO. Each variant differs in search direction, in how the target is resolved, and in how it interacts with the renumbering functions of the SINUMERIK HMI editor and with upstream CAM post-processors. The statements are documented in the official programming manuals distributed on the Siemens Industry Online Support (SIOS) portal.
According to the SINUMERIK ONE NC Programming Manual (SIOS document ID 109817114), GOTOF is defined as a "jump statement with jump destination toward the end of the program," while GOTOB searches toward the beginning of the program. The bidirectional GOTO variant first attempts the search in the forward direction and falls back to the backward direction if the label is not located ahead of the jump. The same definitions appear in the SINUMERIK 840D sl / 828D Programming Manual (SIOS ID 109748381), confirming that the syntax is identical across the three controller families.
Compared with structured control flow (IF...THEN...ELSE...ENDIF, FOR, WHILE, REPEAT...UNTIL, and CASE), unconditional jumps are typically reserved for short branch points, retry logic, and rough-and-finish branching. Practical CNC programs that rely only on block numbers tend to break when an operator re-numbers the program; the label variant introduced for 840D is the documented mechanism to make jump targets robust against renumbering.
GOTOF / GOTOB / GOTO Syntax and Search Direction
| Statement | Argument | Search Direction | Typical Use Case |
|---|---|---|---|
GOTOF <target> |
Label name with colon or N-block number | Forward (toward program end) | Skip past optional features, exit roughing early, fan out to multiple downstream passes |
GOTOB <target> |
Label name with colon or N-block number | Backward (toward program start) | Build mill-turn loops, restart sub-operations, re-attempt clamped work after springback |
GOTO <target> |
Label name with colon or N-block number | Forward first, then backward | Single label definition used by both directions, framework / dispatcher patterns |
The exact argument to GOTOF, GOTOB, or GOTO is the identifier of the jump target. The identifier can be either:
- An NC block number such as
N30. Block numbers are mandatory in classical DIN/ISO NC programs and are still used in post-processed programs. - A label terminated with a colon, such as
SCHLICHTEN:. The label form is an 840D extension that survives renumbering and is the recommended long-term form.
Inside a block, only one GOTO-family statement may appear per NC block. Mixing a GOTOF with a second motion or auxiliary-function call in the same block produces a parser warning on newer SINUMERIK firmwares; the conventional practice is to place the jump on its own block so that the lookahead of the block sequencer can prepare the upcoming motion commands.
Label Definition Rules and Block Numbers
A label in an 840D program is the identifier directly followed by a colon. The colon character is mandatory; it tells the parser that the rest of the block belongs to the next statement and not to the label. The label itself acts like a main block: it can carry block numbers and can be targeted by both GOTOF and GOTOB.
N06 ANFANG:
N10 GOTOF SCHLICHTEN
...
...
N30 SCHLICHTEN:
...
...
N40 GOTOB ANFANG
The example above defines a forward jump from N10 to the label SCHLICHTEN: defined at N30, then a backward jump from N40 back to ANFANG: at N06. Because the targets use named labels, the program remains valid if the absolute block numbers change from N06 to N106, because the GOTO targets resolve by name, not by number.
The rules for valid label identifiers are consistent with the rules for identifiers in the Siemens high-level language:
- Label names start with a letter or an underscore.
- Subsequent characters may be letters, digits, or underscores.
- Labels are not case-sensitive on classic 840D controllers; case-sensitive parsing is firmware-dependent.
- The colon terminates the label within its block.
- Labels must be unique within a program if the program is parsed in non-extended mode; macro redefinition is not allowed.
If a label is defined twice in the same program, the first definition wins for forward search, the second definition wins for backward search, and GOTO behaves according to the parser's tie-breaking rule. The recommended practice is one definition per program and one definition per subroutine.
Comment Character Pitfalls and Common Parser Errors
The semicolon (;) is the SINUMERIK comment introducer in both 840D sl and ONE programs. Anything on the same block to the right of the first semicolon is ignored by the parser. This creates a specific failure mode for jump statements: writing GOTOF ;AAA would produce an empty argument because ;AAA is treated as a comment, which means the jump has no target and the parser raises a syntax error.
The buggy form and the correct form are:
; WRONG: GOTOF ;AAA ; the part after ; is the comment, target is empty
; RIGHT: GOTOF AAA ; AAA is the target identifier
; ALSO RIGHT: GOTOF AAA ; SEMICOLON STARTS THE COMMENT AFTER THE TARGET
Because the colon that terminates a label and the semicolon that opens a comment are adjacent punctuation characters, a label of the form SCHLICHTEN; is interpreted as SCHLICHTEN followed by an empty comment, not as a label definition. The correct form is SCHLICHTEN: with a colon.
; can therefore silently swallow the target. Validate the program with the SINUMERIK simulator (HMI simulation on a non-production NCU) before running on the machine.Conditional Jumps with IF ... GOTO
For branches that depend on a process value, the structured alternative to GOTOF and GOTOB is the IF ... GOTOF pattern documented in the same SINUMERIK manuals. IF accepts a relational expression and applies the jump only when the condition is true. IF can be combined with both GOTOF and GOTOB, and can be nested for multi-way branching.
; Conditional branch based on finishing allowance
DEF NCK INT AUFMASS = 0
AUFMASS = 10
N10 IF AUFMASS == 0 GOTOF NO_REWORK
N20 IF AUFMASS <= 5 GOTOF LIGHT_REWORK
N30 GOTOF HEAVY_REWORK
N40 NO_REWORK: ; clean part, skip rework station
G0 X0 Y0 Z100
GOTOF END_PROGRAM
N50 LIGHT_REWORK: ; one light finishing pass
CYCLE<"FINISH">(1, 0.5)
GOTOF END_PROGRAM
N60 HEAVY_REWORK: ; full re-cut with the recorded allowance
CYCLE<"FINISH">(2, AUFMASS)
N70 END_PROGRAM:
M30
The above pattern is process-safe in the sense that the choice of rework station is governed by the value of the placeholder AUFMASS rather than by a fragile block-number chain. Because the targets are labels, re-numbering the rough block sequence does not break the dispatch.
The boolean expression in IF accepts the standard comparison operators ==, <>, <, <=, >, and >=; the logical operators AND, OR, and NOT; and parentheses for grouping. Bitwise operators are also available on the integer types. See the section "Control structures: conditional branches" in the linked programming manual for the complete grammar.
DEF Placeholders, R Parameters, and LUD Variables
Conditional jumps become meaningful only when they are conditioned on a value. Three storage classes feed those values in an 840D program:
| Storage Class | Scope | Definition Syntax | Typical Use |
|---|---|---|---|
| R parameters (R0 ... R99, R100+ depending on MD) | Global to the program | Implicit; assign with R10 = 12.5
|
Numeric setpoints from the operator, macro arguments, comparator values |
| Local user data (LUD) | Local to the program; cleared at reset or M30 | DEF NCK INT MYVAL = 0 |
Counters inside loops, transient flags |
| Modal GUD (global user data) | Global across programs, persists across resets |
DEF NCK INT GLOBAL_FLAG in an _N_GUD_DEF or _N_SGUD_DEF block |
Cell-level flags, tool-life counters, fixture status |
Defining a placeholder with DEF requires the keyword DEF, a type qualifier (INT, REAL, BOOL, CHAR, STRING), the identifier, an optional initial value, and a semicolon terminator. The type is checked at runtime; passing a string into an IF comparator that expects an integer triggers a runtime alarm that references the type expected by the operand.
DEF NCK INT AUFMASS = 0
DEF NCK INT PASS_COUNT = 0
DEF NCK BOOL LIGHT_ONLY = FALSE
LIGHT_ONLY = (AUFMASS <= 5)
IF LIGHT_ONLY GOTOF LIGHT_REWORK
PASS_COUNT = PASS_COUNT + 1
Modifying the storage class without restarting the program can leave stale values in the chosen class. The recommended commissioning practice is to clear R parameters in the program prologue (R0 = ... R99 = 0) and to rely on the HMI/PLC handshake for the initial value of any modal placeholder.
Block-Number Targets vs. Label Targets in Practice
The 840D-class extended syntax introduces label targets because renumbering is a routine operation in NC programming environments. Two scenarios illustrate the difference:
| Scenario | Block-number target | Label target |
|---|---|---|
| Operator inserts a comment block between N10 and N20 | If renumbering re-sequences, references stay valid because all N-block numbers move together. | References stay valid because labels are unchanged. |
| CAM post-processor changes block numbering scheme (e.g., N05 step instead of N10 step) | References stay valid because all N-block numbers move together. | References stay valid because labels are unchanged. |
| Operator manually deletes N15 because the line was redundant | If reference was N20, it is unchanged; if reference was N15, the jump becomes an error. | References stay valid because labels are unchanged. |
| Two operators independently edit and renumber subprograms | If subprogram call sites use absolute N-block numbers, refactoring breaks. | Subprogram call sites still resolve. |
The decisive property is that label resolution works at the symbol table of the program unit, while block-number resolution works at the textual level of the source file. Symbolic resolution is robust to deletion, insertion, and renumbering; textual resolution is not.
Beckhoff $GOTO for Cross-Reference
Beckhoff TwinCAT NC I and TF5200 define a $GOTO instruction as part of the high-level NC language. According to the Beckhoff Information System documentation for TF5200, "before and after the $GOTO command, other NC commands can be programmed in the same line; however, the jump is executed only as the last action in the NC block." This deferred-execution rule is the same as for Siemens: any auxiliary functions and modal states in the same block complete before the program counter changes. The label form of the target is supported in the same way as in 840D, but the identifier character set and the maximum identifier length are different from Siemens. When porting NC code between controllers, validate every label name against the destination controller's character set and re-test jumps in offline simulation.
The general concept of a programmatic jump labelled goto as a control-flow statement is the same across both controllers, but only the high-level labeled form is portable in practice. Absolute block-number references are not portable between vendors, nor even between two Siemens controllers with different NC software versions.
Program Architecture with Multiple Jump Targets
Larger NC programs benefit from an explicit dispatcher pattern: each macro-level branch point is a label, each branch decision is an IF statement, and the dispatcher at the bottom of the program is a single block sequence with a final M30 or REPEAT. A representative multi-station pattern looks like:
; === Prolog: definitions and setpoints ===
DEF NCK INT STATION = 0
DEF NCK REAL ALLOW = 0.0
ALLOW = $AA_IM[X] ; example: read actual machine position
STATION = 1 ; default
IF ALLOW > 5.0 THEN STATION = 3
IF ALLOW > 0.5 GOTOF SET_STATION3
IF ALLOW > 0.1 GOTOF SET_STATION2
STATION = 1
GOTOF END_DISPATCH
SET_STATION2:
STATION = 2
GOTOF END_DISPATCH
SET_STATION3:
STATION = 3
END_DISPATCH:
IF STATION == 1 GOTOF ROUTE_A
IF STATION == 2 GOTOF ROUTE_B
GOTOF ROUTE_C
ROUTE_A:
; ... shape with no rework
GOTOF FINISH_BLOCK
ROUTE_B:
; ... one finishing pass
GOTOF FINISH_BLOCK
ROUTE_C:
; ... full re-cut
FINISH_BLOCK:
M30
This pattern keeps every branch reachable from a label, eliminates forward-only stub code, and survives renumbering. The END_DISPATCH: label is conventional for the end of the dispatch decision; the assembler does not require it but the convention clarifies intent for human reviewers.
CONTPRON, CONTDCF, or explicit : continuations, a GOTOF is recognized as a block boundary by the block sequencer but may still split a continuous motion if the lookahead buffer is short. For contour-sensitive work, prefer IF...THEN...ELSE...ENDIF to keep the branch decision outside the active look-ahead chain. See the chapter "Behavior of program jumps with continuous-path" in the Siemens programming manual.Renumbering Behavior and Long-Term Maintenance
The Siemens HMI offers a renumbering function that re-sequences block numbers in a defined step (default 10). The function does not change label definitions and does not change jump arguments, so the program continues to behave identically after renumbering. Manual renumbering via the NC editor is not always available; CAM post-processors often emit final programs with the production numbering scheme requested by the user.
The recommended layout for any program that uses jumps is:
- Use a defined block-number step (e.g., N05) to give each block room for inline insertions.
- Define labels in their own blocks, optionally with a leading N-block number for backward search compatibility.
- Target labels by name in every
GOTOF,GOTOB, andGOTO. - Wrap dispatch patterns with
IF...THEN...ENDIFto keep them independent of the jump target. - Document the renumbering step and the label policy in the program header comment.
If the program needs to be a label-only program (no block numbers at all), set the corresponding machine data per the controller manual; SINUMERIK accepts programs without N numbers as long as labels define the jumpable structure.
Verification: Offline Simulation and Online Tracing
Before a program with unconditional jumps is released to production, verify the program using these checks:
-
Offline simulation: Load the program into the HMI simulation (or into SINUMERIK Operate with "NCK simulation"), step through the program with "Single block" enabled, and confirm that every
GOTOF,GOTOB, andGOTOreaches the documented label. - Cross-reference: Generate a label cross-reference via the HMI dialog (the cross-reference function lists each definition and each use). Confirm that every use resolves to a definition and that there are no orphan definitions.
-
Conditional branch coverage: For each
IFpreceding aGOTOF, run the branch with both a true condition and a false condition. Document the test vectors in the program header. - Motion safety: Confirm that the jump is not mid-contour. If it is, replace it with a structured branch and re-validate with the cutting-force monitoring system active.
-
Alarm response: Configure the PLC axis-specific alarm responses so that the
RESETfrom the PLC does not strand the controller inside a backward-jump loop.
After each release, archive the program with the renumbering-step file and the label cross-reference attached. The combination is the minimum that an auditor needs to reconstruct the program's intended execution path.
Programming Examples (Annotated)
The following two examples compile under SINUMERIK 840D sl with the default "Siemens high-level language" syntax set. Both are reduced from typical shop-floor programs and emphasize the relationship between jump direction, label choice, and process state.
Example 1: Loop with operator-settable pass count
DEF NCK INT PASSES = 0
DEF NCK INT DONE = 0
PASSES = 3
N10 ANFANG:
PASSES = PASSES - 1
IF PASSES < 0 GOTOB ENDE
; ... perform one milling pass here ...
GOTOB ANFANG
N20 ENDE:
DONE = 1
M30
Example 2: Conditional rework dispatch
DEF NCK REAL AUFMASS = 0.0
DEF NCK INT LOOP_CTR = 0
LOOP_CTR = 0
N10 MESSEN:
LOOP_CTR = LOOP_CTR + 1
IF LOOP_CTR > 5 GOTOF ALARM_FEHLER
AUFMASS = $AA_IM[Z]
IF AUFMASS < 0.01 GOTOF OK ; part is already in spec
IF AUFMASS < 0.10 GOTOF LIGHT ; light finishing
GOTOF HEAVY ; full re-cut
OK:
GOTOF ENDE
LIGHT:
CYCLE<"FINISH">(1, 0.05)
GOTOB MESSEN
HEAVY:
CYCLE<"FINISH">(2, AUFMASS)
GOTOB MESSEN
ALARM_FEHLER:
; raise an operator alarm and exit
MSG("Rework could not converge")
M0
ENDE:
M30
The second example uses GOTOB MESSEN to return to a measurement block, which is the canonical "measure-and-rework" pattern on 840D. The dispatch never resolves to absolute block numbers, so renumbering the program does not break the loop.
Troubleshooting Quick Matrix
| Symptom | Likely Cause | Verification | Fix |
|---|---|---|---|
Syntax error "no jump target" on GOTOF
|
Trailing semicolon swallowed target | View the block in the editor and check characters after GOTOF | Remove the leading semicolon and rewrite as GOTOF MYLABEL ; comment
|
| Jump goes to the wrong block after edit | Absolute block-number reference moved | Check the cross-reference for the target label | Convert the target to a label and rename blocks accordingly |
| Continuous-path motion is interrupted by jump | Jump sits inside a contour block group | Inspect the G-group and the lookahead buffer | Replace GOTOF with IF...ELSE...ENDIF
|
GOTO jumps backward although forward target exists |
Identifier collision due to duplicate label | Run cross-reference and count definitions | Rename one of the duplicate labels |
| Runtime alarm "type mismatch" after IF...GOTO branch | Storage class assigned a wrong-typed value | Check the DEF qualifier and the runtime assignment |
Use the correct type qualifier and add an explicit conversion |
GOTOF never taken although condition true |
Modal GUD value stale from a prior program | Reset the program and inspect the placeholder | Set the placeholder in the prologue and reset it in the HMI |
What is the difference between GOTOF, GOTOB, and GOTO on SINUMERIK 840D?
GOTOF searches forward only from the current block toward the end of the program, GOTOB searches backward only toward the beginning, and GOTO performs a bidirectional search, attempting forward first and falling back to backward. The definitions are documented in the SINUMERIK 840D sl / 828D Programming Manual.
Why does GOTOF ;AAA produce a syntax error on a 840D?
The semicolon is the comment character on SINUMERIK, so ;AAA is a comment, not a target. The GOTOF has no argument and the parser raises an error. Use GOTOF AAA instead, with or without a trailing comment after the identifier.
Can I jump to a label with a colon on 840D?
Yes. A label such as SCHLICHTEN: defined in its own block is recognized as a valid target for GOTOF, GOTOB, and GOTO. The colon terminates the label within the block. Labeled targets survive renumbering; absolute block-number targets do not.
How do I make a jump depend on a process value?
Combine the jump with IF: IF AUFMASS > 0.5 GOTOF LIGHT_REWORK. The condition accepts standard comparison operators, logical operators, and parentheses. See the conditional branch section of the linked programming manual for the full grammar.
Is there a portable "goto" concept across Siemens and Beckhoff NC controllers?
The label-jump form is conceptually portable, but the identifier character set, maximum label length, and exact semantics of same-block execution differ. Beckhoff TF5200 documents $GOTO as a deferred-action command within an NC block. Validate cross-vendor programs in offline simulation before production release.