Project

General

Profile

crt0.s

abondarev, 07/30/2015 08:25 PM

 
1
.include "aliases.inc"
2
.include "R1_pcf.inc"
3

    
4
; Константы системные:
5
.global PSW.ONIRQS      ; Признак обработки немаскируемых прерываний
6
.equiv  PSW.ONIRQS,       0x0001
7
.global INTR.PRGE       ; Немаскируемое программное исключение
8
.equiv  INTR.PRGE,        0x0008
9

    
10
.alias divsl divsl.crt
11
.alias divl divl.crt
12

    
13
; Глобальные имена:
14
.global irq.desc.tbl    ; Таблица векторов прерываний.
15
.global sizeof.IDT.item ; Размер элемента таблицы векторов прерываний.
16
.equiv  sizeof.IDT.item,  sizeof.ptr
17
.global __libc_main     ; Ф-ция инициализации стандартной библиотеки Си.
18
.global main            ; Главная ф-ция задачи.
19
.global divsl           ; Деление знаковых чисел.
20
.global divl            ; Деление беззнаковых чисел.
21
.global movb            ; Копирование участком памяти байтами.
22
.global movl            ; Копирование участком памяти словами.
23
.global movq            ; Копирование участком памяти двойными словами.
24
;Функции
25
.global asm_getl_PSW 		; Функция getl #PSW из ассемблера
26
.global asm_setl_PSW 		; Функция setl #PSW из ассемблера
27
.global asm_getl_MSKR 		; Функция getl #MSKR из ассемблера
28
.global asm_setl_MSKR 		; Функция setl #MSKR из ассемблера
29
.global asm_getl_INTR 		; Функция getl #INTR из ассемблера
30
.global asm_setl_INTR 		; Функция setl #INTR из ассемблера
31
.global asm_getl_INTNUM  	; Функция getl #INTNUM из ассемблера
32
.global asm_getl_PLLCR 		; Функция getl #PLLCR из ассемблера
33
.global asm_setl_PLLCR 		; Функция setl #PLLCR из ассемблера
34
.global asm_getl_PLLSTR		; Функция getl #PLLSTR из ассемблера
35
.global asm_setl_PLLSTR		; Функция setl #PLLSTR из ассемблера
36
.global asm_getl_PLLTMCR 	; Функция getl #PLLTMCR из ассемблера
37
.global asm_setl_PLLTMCR 	; Функция setl #PLLTMCR из ассемблера
38
.global asm_set_PLL         ; функция настройки PLL
39

    
40
;Пользовательские прерывания
41
.global  set_irq_vector ; Функция для установки пользовательского прерывания
42

    
43
; Локальные имена:
44
.local master.isr       ; Первичный обработчик прерываний.
45
.local tsk.retval       ; Код завершения задачи.
46

    
47
;===============================================================================
48
; Interrupt Descriptor Table (IDT): Таблица векторов прерываний
49
;===============================================================================
50
.data
51
.align 4
52

    
53
  irq.desc.tbl:
54
    .long \
55
	0, \
56
	0, \
57
	0, \
58
	0, \
59
	0, \
60
	0, \
61
	0, \
62
	0, \
63
	0, \
64
	0, \
65
	0, \
66
	0, \
67
	0, \
68
	0, \
69
	0, \
70
	0, \
71
	0, \
72
	0, \
73
	0, \
74
	0, \
75
	0, \
76
	0, \
77
	0, \
78
	0, \
79
	0, \
80
	0, \
81
	0, \
82
	0, \
83
	0, \
84
	0, \
85
	0, \
86
	0, \
87
	0, \
88
	0, \
89
	0, \
90
	0, \
91
	0, \
92
	0, \
93
	0, \
94
	0, \
95
	0, \
96
	0, \
97
	0, \
98
	0, \
99
	0, \
100
	0, \
101
	0
102
	;0, \ ;//ENMI.isr,
103
	;0 ;//RESERVED.isr,
104
      ; 0, \ ;//PERE.isr,
105
      ; 0, \ ;//PPGE.isr,
106
      ; 0, \;//RESERVED.isr,
107
      ; 0, \;//RESERVED.isr,
108
      ; 0, \;//WKUP.isr,
109
      ; 0, \;//DTC0.isr,
110
      ; 0, \;//ST0.isr,
111
	  ; 0, \;//ST1.isr,
112
	  ; 0, \;//ST2.isr,
113
      ; 0, \;//ST3.isr,
114
      ; 0, \;//SW0.isr,
115
	  ; 0, \;//SW1.isr,
116
      ; 0, \;//SW2.isr,
117
      ; 0, \;//SW3.isr,
118
      ; 0, \;//ADC0.isr,
119
      ; 0, \;//DAC0.isr,
120
      ; 0, \;//ADC1.isr,
121
      ; 0, \;//DAC1.isr,
122
      ; 0, \;//UART0.isr,
123
	  ; 0, \;//UART1.isr,
124
	  ; 0, \;//UART2.isr,
125
	  ; 0, \;//UART3.isr,
126
      ; 0, \;//I2C0.isr,
127
	  ; 0, \;//I2C1.isr,
128
      ; 0, \;//SPI0.isr,
129
	  ; 0, \;//SPI1.isr,
130
      ; 0, \;//I2S0.isr,
131
      ; 0, \;//GPTIM0.isr,
132
	  ; 0, \;//GPTIM1.isr,
133
	  ; 0, \;//GPTIM2.isr,
134
	  ; 0, \;//GPTIM3.isr,
135
      ; 0, \;//WDT.isr,
136
      ; 0, \;//RTC.isr,
137
      ; 0, \;//GPIOA.isr,
138
	  ; 0, \;//GPIOB.isr,
139
	  ; 0, \;//GPIOC.isr,
140
	  ; 0, \;//GPIOD.isr,
141
	  ; 0, \;//GPIOE.isr,
142
	  ; 0, \;//GPIOF.isr,
143
      ; 0, \;//ETHERNET0.isr,
144
      ; 0, \;//USB0.isr,
145
      ; 0, \;//USB0_EPI.isr,
146
      ; 0, \;//USB0_EPO.isr,
147
      ; 0, \;//PWM0.isr,
148
      ; 0 ;//STAT.isr
149

    
150
;===============================================================================
151
; Interrupt System Timer(IST): Таблица векторов прерываний периферийного таймера
152
;===============================================================================
153

    
154

    
155

    
156
/////////////////////////////////////////
157

    
158
;===============================================================================
159
; Начальный код
160
;-------------------------------------------------------------------------------
161
; - инициализирует стеки
162
; - утанавливает адрес первичного обработчика прерываний
163
; - разрешает обработку прерываний
164
; - уходит на функцию __libc_main определенную в стандартной библиотеке
165
;   которая в свою очередь вызывает ф-цию main программы.
166
; - записывает возвращаемое значение в переменную tsk.retval
167
; - инициирует немаскируемое программное прерывание.
168
;===============================================================================
169
.data
170
  tsk.retval: .long               ; Результат выполнения задачи.
171
  .alias sizeof.tsk.retval sizeof.long
172
  //psw_reset_val: .long
173

    
174
.section .boot, "ax"
175

    
176
__libc_main:
177
 wdt_off:
178
     getl 0x00003333
179
     wrl @1, 0xC00E0004 ; disable watch dog timer
180
     jmp start;
181
 complete
182

    
183
start:
184

    
185
    ; Инициализация стека и указателей стека:
186
    ;     0           #SP      #BP = sizeof.DM
187
    ;     |           |        |
188
    ;     v           v        v
189
    ; DM |...........|....|....|
190
    ;                      ^^^^
191
    ;                 ^^^^ tsk.retval
192
    ;                 #start.stop
193
    ; #SP -- адрес возврата из программы;
194
    ; #BP -- за верхнюю границу DM.
195
    jmp   main
196
    getl  sizeof.DM
197
    getl  0
198
    getl  start.stop
199
    subl  @3, sizeof.tsk.retval
200
    subl  @1, sizeof.ptr
201
    wrl   @4, @2                  ; __libc_main::retval = 0
202
    wrl   @4, @2                  ; __libc_main::retaddr = start.stop
203
    setl  #BP, @7                 ; BP = sizeof (DM)
204
    setl  #SP, @4                 ; SP = BP - sizeof.tsk.retval - sizeof.ptr
205

    
206
    ; Инициализация обработки прерываний:
207

    
208
    setl  #IHOOKADDR, master.isr
209

    
210
	setl #INTR, 0xFFFFFFFF ;обнулим прерывания
211
	setl #MSKR, 0 ;обнулим маску
212

    
213
    getq  #PSW
214
    or    @1, PSW.ONIRQS
215
    setq  #PSW, @1
216

    
217
  complete                        ; => __libc_main
218

    
219

    
220
  start.stop:                     ; <= __libc_main
221

    
222
    ;jmp   start
223

    
224
    ; Копируем возвращаемое значение во статическую переменную.
225

    
226
    rdl   #SP, sizeof.ptr
227
    wrl   @1, tsk.retval
228

    
229
    ; Освобождаем память в стеке.
230

    
231
    getl  #SP
232
    addl  @1, sizeof.ptr + sizeof.tsk.retval
233
    setl  #SP, @1                 ; SP = BP = sizeof.DM
234

    
235
    ; Устанавливаем немаскируемое программное прерывание
236

    
237
    ;setq  #FORCE, INTR.PRGE
238

    
239
  complete
240

    
241
;===============================================================================
242
; __libc_main
243
;-------------------------------------------------------------------------------
244
; Заглушка для ф-ции которая должна предоставляться стандартной библиотекой Си.
245
; Выполняет инициализацию окружения выполнения программы на Си и вызывает
246
; фцнкцию main.
247
;===============================================================================
248
  .alias __libc_main.ret.value  #SP,sizeof.ptr
249

    
250

    
251
 ;===============================================================================
252
; Interrupt Vector Setting (IVS): Установка веторов прерываний
253
; Реализация функции, которая устанавливает пользовательский обработчик прерываний
254
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
255
;
256
; void set_irq_vector(int function, int number_irq);
257
;===============================================================================
258
 set_irq_vector:
259
	rdl #SP + 4 ;function name
260
	rdl #SP + 8 ;irq number
261
    getl irq.desc.tbl
262
    mull @2, sizeof.IDT.item
263
    addl @1, @2
264
	wrl @5, @1 ;set irq vector
265
	;rdl #SP
266
    ;jmp @1
267
    jmp [#SP]
268
 complete
269

    
270

    
271
;===============================================================================
272
; Interrupt Service Routine (ISR): Обработчик прерываний
273
;===============================================================================
274
; Нереентерабельная обработка прерываний.
275

    
276
.data
277

    
278
  .local master.isr.retaddr
279
  master.isr.retaddr: .long   ; Адрес возврата из прерывания.
280
  test_irq_psw: .long ;Тестим прерывания
281

    
282
.text
283

    
284
  master.isr:
285

    
286
    ; Формируем переход на обработчик прерывания
287
    ; по адресу из таблицы прерываний.
288
    ; Стек не трогается т.к. в нем могут передаваться аргументы для
289
    ; программного прерывания, за исключением того, что добавляем в стек
290
    ; адрес возврата на окончание первичного обработчика прерывания.
291
	; Кроме того проверяем задан ли вектор прерывания.
292

    
293
    getl  #SP
294
    getl  master.isr.stop
295
    getl  #INTNUMR
296
    getl  #IRETADDR
297
    getl  irq.desc.tbl
298
    mull @3, sizeof.IDT.item
299
    addl @1, @2
300
    rdl   @1
301
	je @1, master.isr.stop
302
	jne @2, @2
303
    subl  @10, sizeof.ptr
304
    wrl   @10, @1
305
    setl  #SP, @2
306

    
307
    ; Сохраняем адрес возврата из прерывания.
308

    
309
    wrl   @10, master.isr.retaddr
310
    ; Обнуляем прерывание в регистре INTR
311
    getl 1
312
    sllq @1, @13
313
    setq #INTR, @1
314
  complete
315

    
316
  master.isr.stop:
317

    
318
    ; Возвращаемся из прерывания:
319

    
320
    rdl   master.isr.retaddr
321
    jmp   @1
322

    
323
    ; Разрешаем прерывания:
324

    
325
    getq  #PSW
326
    or    @1, PSW.ONIRQS
327
    setq  #PSW, @1
328

    
329
    getl #SP
330
    addl @1, sizeof.ptr
331
    setl #SP, @1
332

    
333
  complete
334

    
335
  STUB.isr:
336
    rdl   #SP
337
    jmp   @1
338
  complete
339

    
340

    
341
;===============================================================================
342
; Целочисленное деление знаковых слов.
343
; (Использует алгоритм беззнакового деления.)
344
; Если делитель ноль, то результат не определен.
345
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
346
;
347
;   union Result {
348
;     uint64_t value;
349
;     struct {
350
;       int32_t Quotient;
351
;       int32_t Remainder;
352
;     } fields;
353
;   }
354
; Result divsl (int32_t Numerator, int32_t Denominator);
355
;
356
; 1. Изменить знак у делимого если оно отрицательное. Сделать тоже для делителя.
357
; 2. Преобразовать делимое и делитель в беззнаковое значение.
358
; 3. Использовать алгоритм беззнакового деления.
359
; 4. Преобразовать частное и остаток в знаковое представление.
360
; 5. Изменить знак частного, если знаки делимого и делителя были различные.
361
; 6. Если делимое отрицательное, изменить знак остатка.
362
;===============================================================================
363

    
364
.text
365

    
366
  .alias div.Denominator  #BP, +20
367
  .alias div.Numerator    #BP, +16
368
  .alias div.Remainder    #BP, +12
369
  .alias div.Quotient     #BP, +8
370
  .alias div.RetAddr      #BP, +4
371
  .alias div.PrevBP       #BP
372
  .alias div.Index        #BP, -4
373

    
374
  .alias div.arg.Denominator  #SP, -4
375
  .alias div.arg.Numerator    #SP, -8
376
  .alias div.arg.Remainder    #SP, -12
377
  .alias div.arg.Quotient     #SP, -16
378
  .alias div.arg.RetAddr      #SP, -20
379

    
380
  .alias div.sizeof.args      4*sizeof.long
381

    
382
  .alias div.res.Remainder    #SP, +8
383
  .alias div.res.Quotient     #SP, +4
384

    
385
  divsl:
386
  divsl.prologue:
387

    
388
    jmp   divsl.check.numerator
389

    
390
    getl  #SP
391
    getl  #BP
392
    subl  @2, sizeof.ptr
393
    wrl   @2, #SP,-sizeof.ptr
394
    setl  #SP, @2
395
    setl  #BP, @3
396

    
397
  complete
398
  divsl.check.numerator:               ; if (N < 0)
399

    
400
    rdsl   div.Numerator
401
    js    @1, divsl.neg.num
402
    jns   @2, divsl.pos.num
403
    wrl	  @0,0x7FFFC
404

    
405
  complete
406
  divsl.neg.num:                       ; if (D < 0)
407

    
408
    rdsl   div.Denominator
409
    js    @1, divsl.neg.num.neg.denom
410
    jns   @2, divsl.neg.num.pos.denom
411
    wrl	  @0,0x7FFFC
412

    
413
  complete
414
  divsl.neg.num.neg.denom:             ; divl (-N,-D)
415

    
416
    jmp   divl
417

    
418
    getl  #SP
419

    
420
    rdsl  div.Denominator
421
    rdsl  div.Numerator
422
    getl  divsl.neg.num.neg.denom.returns
423

    
424
    insubsl @3, 0
425
    insubsl @3, 0
426
    subl  @6, div.sizeof.args + sizeof.ptr
427

    
428
    wrsl  @3, div.arg.Denominator
429
    wrsl  @3, div.arg.Numerator
430
    wrl   @6, div.arg.RetAddr
431

    
432
    setl  #SP, @4
433

    
434
  complete
435
  divsl.neg.num.neg.denom.returns:      ; R = -R
436

    
437
    jmp   divsl.epilogue
438

    
439
    getl  #SP
440

    
441
    rdl   div.res.Remainder
442
    rdl   div.res.Quotient
443

    
444
    insubsl @2, 0
445
    addl  @4, div.sizeof.args + sizeof.ptr
446

    
447
    wrl   @2, div.Remainder
448
    wrl   @4, div.Quotient
449

    
450
    setl  #SP, @3
451

    
452
  complete
453
  divsl.neg.num.pos.denom:              ; divl (-N,D)
454

    
455
    jmp   divl
456

    
457
    getl  #SP
458

    
459
    rdsl  div.Denominator
460
    rdsl  div.Numerator
461
    getl  divsl.neg.num.pos.denom.returns
462

    
463
    insubsl @2, 0
464
    subl  @5, div.sizeof.args + sizeof.ptr
465

    
466
    wrsl  @5, div.arg.Denominator
467
    wrsl  @3, div.arg.Numerator
468
    wrl   @5, div.arg.RetAddr
469

    
470
    setl  #SP, @4
471

    
472
  complete
473
  divsl.neg.num.pos.denom.returns:      ; Q = -Q; R = -R;
474

    
475
    jmp   divsl.epilogue
476

    
477
    getl  #SP
478

    
479
    rdl   div.res.Remainder
480
    rdl   div.res.Quotient
481

    
482
    insubsl @2, 0
483
    insubsl @2, 0
484
    addl  @5, div.sizeof.args + sizeof.ptr
485

    
486
    wrl   @3, div.Remainder
487
    wrl   @3, div.Quotient
488

    
489
    setl  #SP, @3
490

    
491
  complete
492
  divsl.pos.num:                        ; if (D < 0)
493

    
494
    rdsl  div.Denominator
495
    js    @1, divsl.pos.num.neg.denom
496
    jns   @2, divsl.pos.num.pos.denom
497
    wrl	  @0,0x7FFFC
498

    
499
  complete
500
  divsl.pos.num.neg.denom:              ; divl (N,-D)
501

    
502
    jmp   divl
503

    
504
    getl  #SP
505

    
506
    rdsl  div.Denominator
507
    rdsl  div.Numerator
508
    getl  divsl.pos.num.neg.denom.returns
509

    
510
    insubsl @3, 0
511
    subl  @5, div.sizeof.args + sizeof.ptr
512

    
513
    wrsl  @2, div.arg.Denominator
514
    wrsl  @5, div.arg.Numerator
515
    wrl   @5, div.arg.RetAddr
516

    
517
    setl  #SP, @4
518

    
519
  complete
520
  divsl.pos.num.neg.denom.returns:      ; Q = -Q
521

    
522
    jmp   divsl.epilogue
523

    
524
    getl  #SP
525

    
526
    rdl   div.res.Remainder
527
    rdl   div.res.Quotient
528

    
529
    insubsl @1, 0
530
    addl  @4, div.sizeof.args + sizeof.ptr
531

    
532
    wrl   @4, div.Remainder
533
    wrl   @3, div.Quotient
534

    
535
    setl  #SP, @3
536

    
537
  complete
538
  divsl.pos.num.pos.denom:               ; divl (N,D)
539

    
540
    jmp   divl
541

    
542
    getl  #SP
543

    
544
    rdsl  div.Denominator
545
    rdsl  div.Numerator
546
    getl  divsl.pos.num.pos.denom.returns
547

    
548
    subl  @4, div.sizeof.args + sizeof.ptr
549

    
550
    wrsl  @4, div.arg.Denominator
551
    wrsl  @4, div.arg.Numerator
552
    wrl   @4, div.arg.RetAddr
553

    
554
    setl  #SP, @4
555

    
556
  complete
557
  divsl.pos.num.pos.denom.returns:
558

    
559
    jmp   divsl.epilogue
560

    
561
    getl  #SP
562

    
563
    rdl   div.res.Remainder
564
    rdl   div.res.Quotient
565

    
566
    addl  @3, div.sizeof.args + sizeof.ptr
567

    
568
    wrl   @3, div.Remainder
569
    wrl   @3, div.Quotient
570

    
571
    setl  #SP, @3
572

    
573
  complete
574
  divsl.epilogue:
575

    
576
    ; Строим возврат.
577

    
578
    rdl   div.RetAddr
579
    jmp   @1
580

    
581
    getl  #BP
582
    rdl   div.PrevBP
583
    setl  #BP, @1
584
    addl  @3, sizeof.ptr
585
    setl  #SP, @1
586
    wrl	  @0,0x7FFFC
587

    
588
  complete
589

    
590
;==============================================================================
591
; Целочисленное деление беззнаковых слов.
592
; Если делитель ноль, то результат не определен.
593
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
594
;
595
;   union Result {
596
;     uint64_t value;
597
;     struct {
598
;       uint32_t Quotient;
599
;       uint32_t Remainder;
600
;     } fields;
601
;   }
602
; Result divl (uint31_t Numerator, uint31_t Denominator);
603
;==============================================================================
604

    
605
  divl:
606
  divl.prologue:
607

    
608
    jmp   divl.arg.check
609

    
610
    getl  #SP
611
    getl  #BP
612
    subl  @2, sizeof.ptr
613
    wrl   @2, #SP,-sizeof.ptr
614
    setl  #SP, @2
615
    setl  #BP, @3
616

    
617
  complete
618
  divl.arg.check:                       ; Делимое должно быть больше делителя.
619

    
620
    rdl   div.Numerator
621
    rdl   div.Denominator
622

    
623
/*  Из-за аппаратной ошибки выставления флага переноса/заёма
624
*   этот код для некоторых значений работает неправильно
625
*    subl  @2, @1                        ; if ( N < D )
626
*    jb    @1, divl.simple.result
627
*    jae   @2, divl.prepare
628
*/
629

    
630
    maxl  @1, @2
631
    subl  @3, @1                        ; if ( N < D )
632
    jne    @1, divl.simple.result
633
    je   @2, divl.prepare
634
    wrl	  @0,0x7FFFC
635

    
636
  complete
637

    
638
  divl.simple.result:                   ; Если делимое все таки меньше делителя, то оно и есть остаток.
639

    
640
    jmp   divl.epilogue
641
    getl  0
642
    rdl   div.Numerator
643
    wrl   @2, div.Quotient
644
    wrl   @2, div.Remainder
645

    
646
  complete
647
  divl.prepare:                         ; Выравниваем делитель таким образом, что знакоместо старшего бита
648
                                        ; делителя соответствует знакоместу старшего бита делимого.
649
    jmp   divl.check.remainder
650
    rdl   div.Numerator
651
    rdl   div.Denominator
652
                                        ; За компанию, превращаем делимое в остаток,
653
                                        ; чем оно и будет являться на протяжении выполнения алгоритма.
654
    wrl   @2, div.Remainder
655
    norml @3                            ; Позиция старшего значащего бита делимого
656
    norml @3                            ; Позиция старшего значащего бита делителя,
657
                                        ; должна быть <= чем у делимого,
658
                                        ; т.к. исходим из условия, что делимое > делителя.
659
    subl  @1, @2                        ; Расстояние на которое нужно сдвинуть делитель
660
                                        ; чтобы старшие значащие биты делимого и делителя совпадали.
661
    slll  @5, @1                        ; Сдвигаем делитель таки образом,
662
                                        ; чтобы старшие значащие биты делимого и делителя
663
                                        ; совпадали по знакоместу.
664
    wrl   @1, div.Denominator
665
                                        ; Устанавливаем бит базы-индекса в позицию старшего значащего бита делителя.
666
    getl  1                             ; Выставляем бит базы-индекса...
667
    slll  @1, @4                        ; ... и сдвигаем ее так же как и делитель.
668
    wrl   @1, div.Index
669
                                        ; Обнуляем начальное значение частного.
670
    getl  0
671
    wrl   @1, div.Quotient
672

    
673
  complete
674
  divl.check.remainder:                 ; Проверяем условие подбора очередной степени частного.
675
                                        ; Если в данной позиции (степени) делителя остаток больше делителя, то
676
                                        ; значит можно вычесть из остатка данную степень делителя и, соответсвенно,
677
                                        ; скорректировать частное.
678
                                        ; Иначе -- понижаем степень делителя.
679
    rdl   div.Remainder
680
    rdl   div.Denominator
681

    
682
/*  Из-за аппаратной ошибки выставления флага переноса/заёма
683
*   этот код для некоторых значений работает неправильно
684
*    subl  @2, @1                        ; if R < D
685
*    jb    @1, divl.next.order
686
*    jae   @2, divl.calculate.remainder
687
*/
688

    
689
    maxl @1, @2
690
    subl @3, @1
691
    jne    @1, divl.next.order
692
    je   @2, divl.calculate.remainder
693
    wrl	  @0,0x7FFFC
694

    
695
  complete
696
  divl.calculate.remainder:             ; Вычисляем остаток и частное.
697

    
698
    jmp   divl.next.order
699
    rdl   div.Remainder
700
    rdl   div.Denominator
701
    subl  @2, @1                        ; Вычисляем остаток:     (R-D').
702
    wrl   @1, div.Remainder             ; Сохраняем остаток: R <- (R-D').
703

    
704
    rdl   div.Quotient                  ; Частное.
705
    rdl   div.Index
706
    addl  @2, @1                        ; Складываем частное с базой-индексом: Q'+I
707
    wrl   @1, div.Quotient              ; Запоминаем частное: Q'<=(Q'+I)
708

    
709
  complete
710
  divl.next.order:                      ; Сдвигаемся к следующему разряду.
711

    
712
    rdl   div.Denominator
713
    rdl   div.Index
714
    slrl  @2, 1                         ;     (D'>>1)
715
    slrl  @2, 1                         ;     (I >>1)
716
    wrl   @2, div.Denominator           ; D'<=(D'>>1)
717
    wrl   @2, div.Index                 ; I <=(I >>1)
718
                                        ; Проверяем что все разряды обработаны.
719
                                        ; if (I == 0) // База-индекс в младщем разряде.
720
    je    @3, divl.epilogue             ; then Алгоритм завершен
721
    jne   @4, divl.check.remainder
722
    wrl	  @0,0x7FFFC
723

    
724
  complete
725
  divl.epilogue:
726

    
727
    ; Строим возврат.
728

    
729
    rdl   div.RetAddr
730
    jmp   @1
731

    
732
    getl  #BP
733
    rdl   div.PrevBP
734
    setl  #BP, @1
735
    addl  @3, sizeof.ptr
736
    setl  #SP, @1
737
    wrl	  @0,0x7FFFC
738

    
739
  complete
740

    
741

    
742

    
743

    
744
;===============================================================================
745
; Реализация функции, которая выполняет команду setl в регистр #PSW аналогично ассемблеру
746
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
747
;
748
; void asm_setl_PSW(int ARG1);
749
;
750
;===============================================================================
751

    
752
asm_setl_PSW:
753
    rdl #SP
754
	rdl #SP + 4 ;значение пользователя для PSW
755
	setl #48, @1
756
	jmp @3
757
complete
758

    
759
;===============================================================================
760
; Реализация функции, которая выполняет команду getl в регистр #PSW аналогично ассемблеру
761
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
762
;
763
; int asm_getl_PSW();
764
;
765
;===============================================================================
766

    
767
asm_getl_PSW:
768
    getl #48
769
	wrl @1, #SP + 4 ;текущее значение PSW
770
    rdl #SP
771
	jmp @1
772
complete
773

    
774
;===============================================================================
775
; Реализация функции, которая выполняет команду setl в регистр #MSKR аналогично ассемблеру
776
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
777
;
778
; void asm_setl_MSKR(int ARG1);
779
;
780
;===============================================================================
781

    
782
asm_setl_MSKR:
783
    rdl #SP
784
	rdl #SP + 4 ;значение пользователя для PSW
785
	setl #50, @1
786
	jmp @3
787
complete
788

    
789
;===============================================================================
790
; Реализация функции, которая выполняет команду getl в регистр #MSKR аналогично ассемблеру
791
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
792
;
793
; int asm_getl_MSKR();
794
;
795
;===============================================================================
796

    
797
asm_getl_MSKR:
798
    getl #50
799
	wrl @1, #SP + 4 ;текущее значение PSW
800
    rdl #SP
801
	jmp @1
802
complete
803

    
804
;===============================================================================
805
; Реализация функции, которая выполняет команду setl в регистр #INTR аналогично ассемблеру
806
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
807
;
808
; void asm_setl_INTR(int ARG1);
809
;
810
;===============================================================================
811

    
812
asm_setl_INTR:
813
    rdl #SP
814
	rdl #SP + 4 ;значение пользователя для PSW
815
	setl #49, @1
816
	jmp @3
817
complete
818

    
819
;===============================================================================
820
; Реализация функции, которая выполняет команду getl в регистр #INTR аналогично ассемблеру
821
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
822
;
823
; int asm_getl_INTR();
824
;
825
;===============================================================================
826

    
827
asm_getl_INTR:
828
    getl #49
829
	wrl @1, #SP + 4 ;текущее значение PSW
830
    rdl #SP
831
	jmp @1
832
complete
833

    
834
;===============================================================================
835
; Реализация функции, которая выполняет команду getl в регистр #INTNUM аналогично ассемблеру
836
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
837
;
838
; int asm_getl_INTNUM();
839
;
840
;===============================================================================
841

    
842
asm_getl_INTNUM:
843
    getl #56
844
	wrl @1, #SP + 4 ;текущее значение PSW
845
    rdl #SP
846
	jmp @1
847
complete
848

    
849
;===============================================================================
850
; Реализация функции, которая выполняет команду setl в регистр #PLLCR аналогично ассемблеру
851
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
852
;
853
; void asm_setl_PLLCR(int ARG1);
854
;
855
;===============================================================================
856

    
857
asm_setl_PLLCR:
858
    rdl #SP
859
	rdl #SP + 4 ;значение пользователя для PLLCR
860
	setl #16, @1
861
	jmp @3
862
complete
863

    
864
;===============================================================================
865
; Реализация функции, которая выполняет команду getl в регистр #PLLCR аналогично ассемблеру
866
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
867
;
868
; int asm_getl_PLLCR();
869
;
870
;===============================================================================
871

    
872
asm_getl_PLLCR:
873
    getl #16
874
	wrl @1, #SP + 4 ;текущее значение PLLCR
875
    rdl #SP
876
	jmp @1
877
complete
878

    
879
;===============================================================================
880
; Реализация функции, которая выполняет команду setl в регистр #PLLSTR аналогично ассемблеру
881
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
882
;
883
; void asm_setl_PLLSTR(int ARG1);
884
;
885
;===============================================================================
886

    
887
asm_setl_PLLSTR:
888
    rdl #SP
889
	rdl #SP + 4 ;значение пользователя для PLLSTR
890
	setl #17, @1
891
	jmp @3
892
complete
893

    
894
;===============================================================================
895
; Реализация функции, которая выполняет команду getl в регистр #PLLSTR аналогично ассемблеру
896
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
897
;
898
; int asm_getl_PLLSTR();
899
;
900
;===============================================================================
901

    
902
asm_getl_PLLSTR:
903
    getl #17
904
	wrl @1, #SP + 4 ;текущее значение PLLSTR
905
    rdl #SP
906
	jmp @1
907
complete
908

    
909
;===============================================================================
910
; Реализация функции, которая выполняет команду setl в регистр #PLLTMCR аналогично ассемблеру
911
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
912
;
913
; void asm_setl_PLLTMCR(int ARG1);
914
;
915
;===============================================================================
916

    
917
asm_setl_PLLTMCR:
918
    rdl #SP
919
	rdl #SP + 4 ;значение пользователя для PLLTMCR
920
	setl #18, @1
921
	jmp @3
922
complete
923

    
924
;===============================================================================
925
; Реализация функции, которая выполняет команду getl в регистр #PLLTMCR аналогично ассемблеру
926
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
927
;
928
; int asm_getl_PLLTMCR();
929
;
930
;===============================================================================
931

    
932
asm_getl_PLLTMCR:
933
    getl #18
934
	wrl @1, #SP + 4 ;текущее значение PLLTMCR
935
    rdl #SP
936
	jmp @1
937
complete
938

    
939
;===============================================================================
940
; Реализация функции, которая выполняет настройку PLL
941
; Интерфейс вызова ф-ции соответствует следующему объявлению в синтаксисе Си:
942
;
943
; int asm_set_PLL(unsigned char RCNT, unsigned char NCNT, unsigned char MXVCO, unsigned char Enable);
944
;
945
;===============================================================================
946

    
947
asm_set_PLL:
948
    rdl #SP + 8 ;RCNT
949
    rdl #SP + 12 ;NCNT
950
    rdl #SP + 20 ;EN
951
    andl @3, 0x7
952
    andl @3, 0x7F
953
    andl @3, 0x1
954
    slll @3, 12
955
    slll @2, 15
956
    addl @4, @2
957
    addl @1, @2
958
    setl #16, @1
959
    jmp asm_wait_pll_lock
960
complete
961

    
962
asm_wait_pll_lock:
963
    getl #17
964
    getl 1
965
    andl @1, @2
966
    je @1, asm_wait_pll_lock
967
    jne @2, asm_pll_set
968
complete
969

    
970
asm_pll_set:
971
    rdl #SP + 8 ;RCNT
972
    rdl #SP + 12 ;NCNT
973
    rdl #SP + 16 ;MXVCO
974
    rdl #SP + 20 ;EN
975
    andl @4, 0x7
976
    andl @4, 0x7F
977
    andl @4, 0xF
978
    andl @4, 0x1
979
    slll @4, 12
980
    slll @3, 8
981
    slll @3, 15
982
    addl @6, @3
983
    addl @3, @2
984
    addl @1, @2
985
    setl #16, @1
986
    rdl #SP
987
	jmp @1
988
complete
989

    
990
.end