حلقه با سربار صفر

در معماری کامیپوتر، **حلقه‌زنی بدون سربار** یک ویژگی سخت‌افزاری است که در برخی پردازنده‌ها یافت می‌شود. این ویژگی اجازه می‌دهد که حلقه‌ها بدون هزینه عملکردی ناشی از دستورات کنترلی معمول حلقه اجرا شوند. به جای آنکه نرم‌افزار تعداد تکرار حلقه را مدیریت کند، پردازنده سخت‌افزار تکرار را بصورت خودکار انجام می‌دهد که باعث صرفه جویی در چرخه‌های کلاک و افزایش کارایی می‌شود. این تکنیک معمولا در پردازشگرهای سیگنال دیجیتال و برخی معماری‌های مجموعه دستورات پیچیده به‌کار می‌رود.

## پیشینه
در بسیاری از مجموعه دستورها، برای پیاده‌سازی یک حلقه باید از دستوراتی استفاده شود که شمارنده را افزایش یا کاهش دهند، تا بررسی کنند که آیا انتهای حلقه رسیده است یا خیر، و در صورت عدم پایان، به ابتدای حلقه پرش کنند تا تکرار ادامه یابد. اگرچه این فرآیند معمولا تنها حدود 3 تا 16 بایت فضا برای هر حلقه اشغال می‌کند، اما حتی همین مقدار کم نیز بسته به اندازه حافظه‌های پنهان یا کش پردازنده می‌تواند مهم باشد. مهم‌تر آن است که اجرای هر یک از این دستورات زمانبر است ولیکن این زمان صرف کار مفیدی نمی‌شود.

سربار چنین حلقه‌ای در مقایسه با حلقه کاملا باز شده نمایان است؛ در حلقه باز شده، بدنه حلقه به همان تعداد باری که اجرا می‌شود، تکثیر خواهد شد. در این حالت هیچ فضای اضافی یا زمان اجرایی روی دستوراتی که صرف تکرار بدنه حلقه می‌شوند، هدر نمی‌رود. با این حال، تکثیر بوجود آمده توسط باز شدن حلقه می‌تواند اندازه کد را بطور قابل توجهی افزایش دهد و این افزایش اندازه حتی ممکن است به دلیل خطا‎‌های حافظه نهان (کش) زمان اجرای برنامه را تحت تاثیر قرار دهد. به همین دلیل رایج است که تنها بخشی از حلقه‌ها باز شوند. مثلا تبدیل آن به یک حلقه که کار چهار تکرار را در یک مرحله قبل انجام دهد و بعد تکرار شود. این کار مزایای باز کردن حلقه با سربار تکرار متعادل می‌کند. بعلاوه، باز کردن کامل حلقه تنها برای دسته محدودی از حلقه‌ها ممکن است: آنهایی که تعداد تکرارشان در زمان کامپایل مشخص است.

برای مثال، کد C زیر می‌تواند توسط کامپایلر به صورت بهینه به کد اسمبلی x86 زیر تبدیل شود:

## پیاده‌سازی‌ها
پردازنده‌هایی که حلقه‌زنی بدون سربار را پشتیبانی می‌کنند دارای دستورالعمل‌ها و رجیسترهایی هستند که می‌توانند یک یا چند دستور را بصورت خودکار تکرار کنند. بسته به دستورالعمل‌*‌‌*‌های موجود، این قابلیت ممکن است تنها برای حلقه‌های کنترل‌شده با شمارنده(حلقه‌‌های "for") که تعداد تکرارها از قبل قابل محاسبه است مناسب باشد، یا تنها برای حلقه‌های کنترل شده با شرط (حلقه‌های "while") مانند عملیات روی رشته های پایان‌یافته با صفر کاربرد داشته باشد.

### مثال‌ها

#### PIC
در مجموعه دستور PIC، دستورهای  و  پیاده‌ سازی حلقه‌زنی بدون سربار را انجام می‌دهند.   فقط یک دستور را تکرار می‌کند، در حالی که  تعداد مشخصی از دستورات بعدی را تکرار می‌کند.

#### Blackfin
بلک فین دو حلقه بدون سربار ارائه می‌دهد.. این حلقه‌ها می‌توانند تو در تو باشند؛ اگر هر دو حلقه سخت افزاری با یک آدرس "پایان حلقه" یکسان تنظیم شده باشند، حلقه 1 بعنوان حلقه درونی رفتار می‌کند و تکرار می‌شود و حلقه 0 بعنوان حلقه بیرونی عمل کرده و تنها در صورتی تکرار می‌شود که حلقه 1 تکرار نشود.

حلقه‌ها با استفاده از رجیسترهای  و  کنترل می‌شوند. ( می‌تواند 0 یا 1 باشد.) برای آنکه بالاترین و پایین‌ترین آدرس حلقه -یعنی اولین و آخرین دستوراتی که اجرا می‌شوند، که برای حلقه‌ای با تنها یک دستور می‌توانند یکسان باشند- تنظیم گردد، و همچنین از  برای شمارنده حلقه استفاده می‌شود. در انتهای حلقه، اگر  ناصفر باشد حلقه تکرار می‌شود و در این حالت  یک واحد کاهش می‌یابد.

رجیسترهای حلقه را می‌توان بصورت دستی نیز مقداردهی کرد، اما این معمولا 6 بایت برای بارگذاری رجیسترها و 8-16 بایت برای آماده‌سازی مقادیری که باید بارگذاری شوند مصرف می‌کند. روش رایج‌تر این است که از دستور تنظیم حلقه استفاده شود ( در اسمبلی یا بصورت  با شبه‌دستور  و  ، و یا در یک تک خط بصورت  نمایش داده می‌شود.) که بطور اختیاری  را مقداردهی اولیه کرده و   و  را به مقادیر دلخواه تنظیم می‌کند. این روش تنها به 4-6 بایت نیاز دارد، اما می‌تواند   و  را فقط در بازه محدودی نسبت به محل قرارگیری دستور تنظیم حلقه قرار دهد.


```c
P0 = a + 396;
R0 = 100;
LC0 = R0;
LOOP my_loop LC0;   // sets LT0 and LB0

LOOP_BEGIN myLoop;   // pseudo-instruction; generates a label used to compute LT0
// LC0 cannot be written directly to memory,
// so we must use a temporary register.
R0 += -1;   // equally fast and small would be R0 = LC0
[P0--] = R0;
LOOP_END myLoop;   // pseudo-instruction; generates a label used to compute LB0
```


#### x86
پیشوندهای  در اسمبلی x86 حلقه های بدون سربار را برای چند دستور محدود ( بویژه  ) پیاده‌سازی می‌کنند. بسته به نوع پیشوند و دستور، آن دستور به تعداد دفعات مشخصی تکرار می‌شود که شمارش آن در رجیستر  قرار دارد، یا تا زمانی که یک تطابق یا عدم تطابق با رجیسترهای  یا با آدرس  یافت شود، ادامه می‌یابد. این قابلیت برای پیاده‌سازی برخی از انواع جستجوها و عملیات روی رشته‌های پایان‌یافته با صفر قابل استفاده است.

## منابع

رده:سخت‌افزار رایانه
رده:معماری رایانه