Subprograms
Subprograms let you repeat a block of code without copying it. This page covers M98/M99, Haas P/L syntax, nested calls, repeating hole patterns, and the safety rules that prevent drift between repetitions.
Concept
A subprogram is a separate O-numbered program called from the main program. On a Haas control, M98 P2000 L3 calls O2000 three times. M99 returns to the line after M98. Subprograms reduce repetition, make programs shorter, and centralize changes — if the hole depth changes, you edit one line instead of sixteen.
Why It Matters
Without subprograms, drilling 16 holes in a pattern means 16 blocks of G81 code. With a subprogram, you write the hole once and call it 16 times. But subprograms inherit modal state — if the subprogram uses G91, the main program must restore G90 after. This is the #1 cause of subprogram bugs: leaked modal state.
How It Works
Haas Syntax
M98 P2000 L3 (call O2000, repeat 3 times)
Inside O2000, M99 returns to the line after M98. The subprogram has its own O-number and lives as a separate program on the machine. On FANUC, the format is similar: M98 P00032000 (repeat 3 times, call O2000). On Haas, L3 means repeat 3 times.
Nested Subprograms
A subprogram can itself call another subprogram (up to 4 levels deep on most controllers). This is how you build reusable building blocks: the main program calls a pattern routine, which calls a single-hole routine. Nested calls return in reverse order: inner M99 returns to the outer M98 line.
Safe Pattern: Always Restore State
Before M98, always: (1) know the current G90/G91 state, (2) ensure G80 cancels any active cycle, (3) declare G90 explicitly after each call. The example below uses absolute coordinates only — no G91 — so there is no drift between holes.
Example: Four-Hole Pattern
Four holes on a 40 mm square at (0,0), (40,0), (40,40), (0,40). The main program positions XY in absolute G90, then calls O2000 which drills at the current position and returns to Z50.
Main program O0029 (entry setup and tool already verified):
O0029 (MAIN - ENTRY SETUP AND TOOL ALREADY VERIFIED)
G21 G17 G90 G94 G40 G80 G98
G00 Z50.
G00 X0. Y0.
M98 P2000
G90 G00 X40. Y0.
M98 P2000
G90 G00 X40. Y40.
M98 P2000
G90 G00 X0. Y40.
M98 P2000
G80
G90 G00 Z50.
M30
Subprogram O2000 (a separate program stored on the machine):
O2000
G90 G98 G81 Z-15. R2. F120.
G80
G90 G00 Z50.
M99
Trace: Call 1 drills at (0,0). Call 2 drills at (40,0). Call 3 drills at (40,40). Call 4 drills at (0,40). Each call: G81 drills at the current XY, G98 retracts to initial plane Z50, G80 cancels cycle, explicit G00 Z50 ensures safe height, M99 returns. Every hole is at Z−15 — no drift.
Note on G80: G80 cancels the canned-cycle mode. After G81 completes, the Z position depends on G98 (retract to initial plane) or G99 (retract to R plane). G80 itself does not retract — that is why we write explicit G00 Z50. after G80.
When to Use Subprograms
- Repeated hole patterns — bolt circles, grid arrays, repeated pocket shapes.
- Multiple identical parts on a tombstone — one subprogram, called at each part origin.
- Repeated features — same chamfer, same groove, same profile at different positions.
- Organization — break a long program into readable chunks by operation.
Common Mistakes
- Confusing P and O — Haas uses M98 P2000 (call), not O2000. The subprogram itself is labeled O2000.
- Using G91 in subprogram without restoring G90 — subsequent main-program coordinates become incremental, causing holes to drift.
- Assuming G80 retracts to Z50 — G80 cancels cycle mode; the return height was set by G98/G99. Always write explicit G00 Z retract.
- Leaving cycle active between calls — cancel with G80 before M99 to make exit state explicit.
- Too many nested levels — most controllers limit nesting to 4 levels. Keep subprograms shallow.
- Modifying offsets inside subprograms — if the subprogram changes H or D, the offset leaks into the next call. Reset offsets explicitly.
Practice
1. M98 P3000 L5 does what?
Ans
Calls O3000 five times, then returns to the line after M98.
2. Why does the subprogram write G90 G00 Z50. before M99?
Ans
To guarantee the tool is at safe height Z50 before returning. G80 cancels cycle mode but does not guarantee Z position; being explicit removes ambiguity.
3. Why does the main program write G90 before each X/Y position?
Ans
To prevent any leftover modal G91 from the subprogram. Declaring G90 explicitly makes each hole position an absolute coordinate, not a delta from the previous one.
4. What is the maximum nesting depth on most controllers?
Ans
Typically 4 levels. A subprogram can call another subprogram, which calls another, up to 4 deep. Beyond that, the controller alarms.