-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrpn_calculator.asm
2031 lines (1761 loc) · 52.2 KB
/
rpn_calculator.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
SECTION INTVEC
B main
SECTION CODE
;Power function
;parameter:
; R0: value to pow
; R1: pow value's
;return:
; R0 = R0^R1
pow
PUSH {R1, R2}
MOV R2, R0
MOV R0, #1
pow_loop
CMP R1, #0
ASSERT N=0;You can't use a negative exponent
BLE pow_end_loop
MUL R0, R0, R2
SUB R1, R1, #1
B pow_loop
pow_end_loop
POP {R1, R2}
BX LR
;Function to right shift a value from a given value
;parameter:
; R0: value to shift
; R1: shift number
;return:
; R0 = R0 >> R1
lsr
PUSH {R1}
lsr_loop
SUBS R1, R1, #1
LSRPL R0, R0, #1
BPL lsr_loop
POP {R1}
BX LR
;Function to left shift a value from a given value
;parameter:
; R0: value to shift
; R1: shift number
;return:
; R0 = R0 << R1
lsl
PUSH {R1}
lsl_loop
SUBS R1, R1, #1
LSLPL R0, R0, #1
BPL lsl_loop
POP {R1}
BX LR
;return: the quotient of the euclidean division
;This function doesn't work with negative number
;parameter:
; R0: dividend
; R1: divisor
;return:
; R0: quotient
; R1: remainder
unsigned_division
PUSH {R2}
MOV R2, #0
CMP R1, #0
ASSERT Z=0 ;ASSERT: you can't divide by zero
division_loop
CMP R0, R1
BLT division_end_loop
SUB R0, R0, R1
ADD R2, R2, #1
B division_loop
division_end_loop
MOV R1, R0
MOV R0, R2
POP {R2}
BX LR
;return: the quotient of the euclidean division
;This function work with negative number
;parameter:
; R0: dividend
; R1: divisor
;return:
; R0: quotient
; R1: remainder
division
PUSH {R2, LR}
CMP R1, #0 ;Test if the divisor is negative
ASSERT Z=0 ;ASSERT: you can't divide by zero
BMI negative_divisor
CMP R0, #0 ;Test if the dividend is negative
BMI negative_dividend
BL unsigned_division;If both are positive we call the unsigned division
B division_return
negative_divisor
RSB R1, R1, #0
BL division
RSB R0, R0, #0
B division_return
negative_dividend
MOV R2, R1 ;Save the divisor value
RSB R0, R0, #0
BL division
CMP R1, #0 ;If remainder is null, we only need to negate the quotient
RSB R0, R0, #0
BEQ division_return
SUB R0, R0, #1;Else we have to perform these operations
RSB R1, R1, R2
division_return
POP {R2, LR}
BX LR
;Test if the given value in ASCII is a number
;parameter:
; R0: value
;return:
; R0: bool
is_ascii_number
SUBS R0, R0, #0x30
CMP R0, #9
MOVGT R0, #0
BXGT LR
CMP R0, #0
MOVGE R0, #1
MOVLT R0, #0
BX LR
;Test if the given last read ASCII character is a number
;parameter:
; R0: calcul_stack address
;return:
; R0: bool
is_number
PUSH {LR, R1}
LDR R0, [R0]
MOV R1, R0
BL is_ascii_number ;Test if it's an number represented in ASCII
CMP R1, #0x2E ;Or a '.' in ASCII to represent a floating point value
MOVEQ R0, #1
POP {LR, R1}
BX LR
;Test if the last read ASCII characters represent a floating point number
;parameter:
; R0: number of ASCII character
; R1: calcul_stack address
;return:
; R0: bool
is_float
PUSH {R1-R3, LR}
MOV R2, R0
MOV R0, R1
BL is_number
CMP R0, #1
BNE is_float_end
MOV R0, #0
is_float_loop
SUBS R2, R2, #1
BMI is_float_end
LDR R3, [R1], #4
CMP R3, #0x2E
MOVEQ R0, #1
BNE is_float_loop
is_float_end
POP {R1-R3, LR}
BX LR
;Convert an integer it's IEE 754 representation
;parameter:
; R0: value
;return:
; R0: IEE 754 value
int_to_IEE_754
PUSH {R1-R3}
;Get the sign of the integer
CMP R0, #0
MOVPL R1, #0
MOVMI R1, #1
MVNMI R0, R0 ;If the number is negative we must perform
ADDMI R0, R0, #1 ;a twos' complement
MOV R2, #127;Initialize the exponent with the bias
MOV R3, #0;Will store the mantissa
int_to_IEE_754_shifting_loop
CMP R2, #0xFF ;If the number is zero
MOVEQ R2, #0
BEQ int_to_IEE_754_shifting_end
CMP R0, #1
BEQ int_to_IEE_754_shifting_end
LSRS R0, R0, #1 ;Shift the mantiss in R3 until we have found the msb
RRX R3, R3
ADD R2, R2, #1
B int_to_IEE_754_shifting_loop
int_to_IEE_754_shifting_end
;Now we only need to extrac the 23 msb of R3
LSR R3, R3, #9
ORR R0, R3, R2, LSL #23 ;And add the exponent to it
ORR R0, R0, R1, LSL #31 ;Add the sign
POP {R1-R3}
BX LR
;FPA less than function
;This function performs return true if the first IEEE 754 value is lower
;than the second IEEE 754 value
;parameter:
; R0: IEEE 754 value
; R1: IEEE 754 value
;return:
; R0: R0 < R1
flt
PUSH {R1-R4, LR}
;We first check if operands are not NaN
PUSH {R0}
BL is_nan
ASSERT R0=0;You can't use this function with an operand that is NaN
MOV R0, R1
BL is_nan
CMP R0, #0
ASSERT R0=0;You can't use this function with an operand that is NaN
POP {R0}
;We then check operands sign
PUSH {R0} ;We get the sign of the first operand
BL get_sign
MOV R2, R0
MOV R0, R1 ;We get the sign of the second operand
BL get_sign
MOV R3, R0
POP {R0}
CMP R2, #0 ;We check if there is sign differences
CMPEQ R3, #1
BEQ flt_pos_neg
CMP R2, #1
CMPEQ R3, #0
BEQ flt_neg_pos
;If they have the same sign we must compare there exponent
PUSH {R0} ;We get the exponent of the first operand
BL get_exponent
MOV R3, R0
MOV R0, R1 ;We get the exponent of the second operand
BL get_exponent
MOV R4, R0
POP {R0}
CMP R2, #0
BEQ flt_pos_pos
BNE flt_neg_neg
flt_pos_neg
MOV R0, #0
B flt_end
flt_neg_pos
MOV R0, #1
B flt_end
flt_pos_pos
CMP R3, R4 ;We compare their exponent
MOVLT R0, #1
BLT flt_end
MOVGT R0, #0
BGT flt_end
BL flt_mantissa
CMP R3, R4 ;We compare their mantissa
MOVLT R0, #1
BLT flt_end
MOV R0, #0
B flt_end
flt_neg_neg
CMP R3, R4 ;We compare their exponent
MOVLT R0, #0
BLT flt_end
MOVGT R0, #1
BGT flt_end
BL flt_mantissa
CMP R3, R4 ;We compare their mantissa
MOVGT R0, #1
BGT flt_end
MOV R0, #0
B flt_end
flt_mantissa
;If they have the same exponent, then we must compare there mantissas
PUSH {R0, LR} ;We get the mantissa of the first operand
BL get_mantissa
MOV R3, R0
MOV R0, R1 ;We get the mantissa of the second operand
BL get_mantissa
MOV R4, R0
POP {R0, LR}
BX LR
flt_end
POP {R1-R4, LR}
BX LR
;FPA greater than function
;This function performs return true if the first IEEE 754 value is greater
;than the second IEEE 754 value
;parameter:
; R0: IEEE 754 value
; R1: IEEE 754 value
;return:
; R0: R0 > R1
fgt
PUSH {R1-R4, LR}
;We first check if operands are not NaN
PUSH {R0}
BL is_nan
ASSERT R0=0;You can't use this function with an operand that is NaN
MOV R0, R1
BL is_nan
CMP R0, #0
ASSERT R0=0;You can't use this function with an operand that is NaN
POP {R0}
;We then check operands sign
PUSH {R0} ;We get the sign of the first operand
BL get_sign
MOV R2, R0
MOV R0, R1 ;We get the sign of the second operand
BL get_sign
MOV R3, R0
POP {R0}
CMP R2, #0 ;We check if there is sign differences
CMPEQ R3, #1
BEQ fgt_pos_neg
CMP R2, #1
CMPEQ R3, #0
BEQ fgt_neg_pos
;If they have the same sign we must compare there exponent
PUSH {R0} ;We get the exponent of the first operand
BL get_exponent
MOV R3, R0
MOV R0, R1 ;We get the exponent of the second operand
BL get_exponent
MOV R4, R0
POP {R0}
CMP R2, #0
BEQ fgt_pos_pos
BNE fgt_neg_neg
fgt_pos_neg
MOV R0, #1
B fgt_end
fgt_neg_pos
MOV R0, #0
B fgt_end
fgt_pos_pos
CMP R3, R4 ;We compare their exponent
MOVLT R0, #0
BLT fgt_end
MOVGT R0, #1
BGT fgt_end
BL fgt_mantissa
CMP R3, R4 ;We compare their mantissa
MOVGT R0, #1
BGT fgt_end
MOV R0, #0
B fgt_end
fgt_neg_neg
CMP R3, R4 ;We compare their exponent
MOVLT R0, #1
BLT fgt_end
MOVGT R0, #0
BGT fgt_end
BL fgt_mantissa
CMP R3, R4 ;We compare their mantissa
MOVLT R0, #1
BLT fgt_end
MOV R0, #0
B fgt_end
fgt_mantissa
;If they have the same exponent, then we must compare there mantissas
PUSH {R0, LR} ;We get the mantissa of the first operand
BL get_mantissa
MOV R3, R0
MOV R0, R1 ;We get the mantissa of the second operand
BL get_mantissa
MOV R4, R0
POP {R0, LR}
BX LR
fgt_end
POP {R1-R4, LR}
BX LR
;Converts read ASCII numbers into value
;parameter:
; R0: number of ASCII character
; R1: calcul_stack address
;return:
; R1: calcul_stack address with new value added in it
convert
PUSH {R2-R6, R10-R12, LR}
MOV R6, SP ;We switch to the calcul_stack
MOV SP, R1
CMP R0, #0
ASSERT N=0, Z=0;You must pass a number of read ASCII character > 0.
;Test if the reading character is a float
PUSH {R0, R1}
BL is_float
MOV R10, R0
POP {R0, R1}
;R11 will store a bool to know if we have found the '.', R12
;the number of floating point read.
MOV R11, #0
MOV R12, #0
MOV R2, #0
MOV R4, #0
convert_loop
CMP R2, R0
BEQ convert_end_loop
POP {R3}
PUSH {R0} ;Test if ASCII value is a number or a prefix operator
MOV R0, R3
BL is_ascii_number
CMP R0, #1
POP {R0}
BEQ convert_number
;Test to see if we are with a float
CMP R10, #1
BNE prefix_operator
CMP R3, #0x2E ;Check if the character is a '.'
BNE convert_no_dot
ASSERT R11=0;You can not have multiple '.' in your declaration.
MOV R11, #1
SUB R0, R0, #1
convert_no_dot
BEQ convert_loop
ASSERT R11=1;You can't have operator in the middle of a float declaration
B prefix_operator
convert_number
SUB R3, R3, #0x30
PUSH {R0, R1} ;Call pow function
MOV R0, #10
MOV R1, R2
BL pow
MUL R3, R3, R0
POP {R0, R1}
ADD R4, R4, R3
ADD R2, R2, #1
CMP R10, #1 ;If we are dealing with a float
CMPEQ R11, #0 ;and we still not have reach the dot
ADDEQ R12, R12, #1 ;we increase the floatin point number
B convert_loop
prefix_operator
SUB R5, R0, R2 ;Calculate the number of remaining ASCII characters
CMP R5, #1
BEQ uniq_prefix
CMP R5, #2
ASSERT Z=1 ;You can't have perfix with more than two ASCII characters
B double_prefix
uniq_prefix
CMP R3, #0x2D
BEQ negative_prefix
CMP R3, #0x2B ;The only perfix with one ASCII character
ASSERT Z=1 ;allowed are + and -
positive_prefix
B convert_end_loop
negative_prefix
RSB R4, R4, #0
B convert_end_loop
double_prefix
;If we are with float we must substract with the good power
CMP R10, #0 ;Else we only need to increment or decrement
MOVEQ R2, #1 ;by one
BEQ double_prefix_scale_end
PUSH {R0, R1} ;Call pow function
MOV R0, #10
SUB R1, R2, #1
BL pow
MOV R2, R0
POP {R0, R1}
double_prefix_scale_end
CMP R3, #0x2D
BEQ decrement_prefix
increment_prefix
CMP R3, #0x2B
ASSERT Z=1
POP {R5} ;The only prefix
CMP R5, #0x2B ;with two ASCII characters
ASSERT Z=1 ;allowed are -- and ++
ADD R4, R4, R2
B convert_end_loop
decrement_prefix
POP {R5} ;The only prefix
CMP R5, #0x2D ;with two ASCII characters
ASSERT Z=1 ;allowed are -- and ++
SUB R4, R4, R2
B convert_end_loop
convert_end_loop
MOV R1, #0x69 ;ASCII 'i' to mark that this value is a integer
CMP R10, #1 ;If we are with a float
BNE convert_no_float ;we convert it into IEE 754 format
PUSH {R0, R1}
MOV R0, R4
MOV R1, R12
BL convert_to_IEE754
MOV R4, R0
POP {R0, R1}
MOV R1, #0x66 ;Change type to 'f' if the value is a float
convert_no_float
PUSH {R4} ;Push the new value in the calcul_stack
PUSH {R1} ;Push the type of the value value in the calcul_stack
MOV R1, SP ;We reswitch to the main stack
MOV SP, R6
POP {R2-R6, R10-R12, LR}
BX LR
;Compact last read hexadecimal into one value
;You can only compact a maximum of 4 hexadecimal values of 1 byte.
;parameter:
; R0: number of read hexadecimals
; R1: calcul_stack address
;return:
; R1: calcul_stack address with new value added in it
compact
PUSH {R2-R5, LR}
MOV R5, SP ;We switch to the calcul_stack
MOV SP, R1
CMP R0, #0
ASSERT N=0, Z=0 ;You must pass a number of read hexadecimals
CMP R0, #5 ;operator between 1
ASSERT N=1 ;and 4 included
MOV R2, #0
MOV R4, #0
compact_loop
CMP R2, R0
BEQ compact_end_loop
POP {R3}
PUSH {R0, R1}
MOV R0, R3
MOV R1, #8
MUL R1, R1, R2
BL lsl
MOV R3, R0
POP {R0, R1}
ORR R4, R4, R3
ADD R2, R2, #1
B compact_loop
compact_end_loop
PUSH {R4} ;Push the new value in the calcul_stack
MOV R1, SP ;We reswitch to the main stack
MOV SP, R5
POP {R2-R5, LR}
BX LR
;Read the transmitted data expression until a separator '[SPACE]' is found
;parameter:
; R0: data address
; R1: calcul_stack address
;return:
; R0: data adresse increased by number of ASCII READ
; R1: calcul_stack address increased by number of ASCII READ
parse
PUSH {R2, R3}
MOV R3, SP
MOV SP, R1
loop_parse
LDRB R2, [R0], #1 ;load ASCII character
CMP R2, #0x20 ;Test if the character is equal to [SPACE]
PUSHNE {R2} ;If not, the carater is push to the stack,
BNE loop_parse ;and we continue the loop
MOV R1, SP
MOV SP, R3
POP {R2, R3}
BX LR
;Function that take a parameter to an RPN calcul and return: it's value
;parameter:
; R0: data address
;return:
; R0: result of the RPN calcul
calculator
PUSH {R1-R3, LR}
BL init_calcul_stack
calculator_loop
PUSH {R1} ;Parse the a list of ASCII characters
BL parse
;Calcul the number of ASCII characters read
MOV R2, R1
POP {R1}
PUSH {R2}
SUB R2, R1, R2
LSR R2, R2, #2
POP {R1}
;Test the last pushed ASCII character to know what to do
PUSH {R0}
MOV R0, R1
BL is_number ;Test if it's a number or an operator
CMP R0, #1
BNE calculator_if_nan ;If it's an operator, we performe the operation
BEQ calculator_if_number ;and if it's a number, we convert it
calculator_if_number;Convert the ASCII characters in their number value
MOV R0, R2
BL convert
POP {R0}
B calculator_loop
calculator_if_nan
LDR R3, [R1] ;Test if it's an '#' or an '@' in hexadecimal used
CMP R3, #0x23 ;to says that hexadecimal value do not represent ASCII
CMPNE R3, #0x40 ;but integers for '#' and float for '@'
BNE calculator_if_operator
;If so
ADD R1, R1, #4 ;We delete the '#' or the '@'
SUB R0, R2, #1 ;and compact the hexadecimals
BL compact ;value on 4 bytes
CMP R3, #0x23
MOVEQ R0, #0x69 ;And we add the type of the value
MOVNE R0, #0x66
STR R0, [R1, #-4]!
POP {R0}
B calculator_loop
calculator_if_operator
MOV R0, R2 ;We first compact the operator on 4 bytes
BL compact
LDR R0, [R1]
CMP R0, #0x3D ;We then test if it is an '='
BEQ end_calculator ;to end the calculator
BL calculation ;Else we perform the calculation
POP {R0}
B calculator_loop
end_calculator
POP {R0}
LDR R0, [R1, #8]
POP {R1-R3, LR}
BX LR
;Convert integer and a number of digits the fractionnal part into
;it's IEEE 754 representation
;parameter:
; R0: number
; R1: number of digit in the fractionnal part
;return:
; R0: IEEE 754 value
convert_to_IEE754
PUSH {R1-R4, LR}
BL int_to_IEE_754 ;We convert the integer into IEEE 754
LDR R2, =0x41200000;We get 10.0 in IEEE 754
LDR R3, =0x3F800000;We get 1.0 in IEEE 754
convert_to_IEE754_loop
SUBS R1, R1, #1
BMI convert_to_IEE754_end
PUSH {R0, R1} ;Get the power of ten
MOV R0, R3 ;that will need to divise
MOV R1, R2 ;the result by to
BL fmul
MOV R3, R0
POP {R0, R1}
B convert_to_IEE754_loop
convert_to_IEE754_end
;We then only need to comput R0 / 10^R1
PUSH {R1}
MOV R1, R3
BL fdiv
POP {R1}
POP {R1-R4, LR}
BX LR
;Make the calcul and push the result in the calcul_stack
;Note that it is supposed that the top of the pile is an operator
;and that their is at least one numbers under it
;parameter:
; R1: calcul_stack address
;return:
; R1: calcul_stack address updated after the calcul
calculation
PUSH {R0, R2-R8, R10, LR}
MOV R8, SP
MOV SP, R1
POP {R0}
LDR R2, =calcul_stack ;We calcul the size of the stack
ADD R2, R2, #400 ;to see if it remain enough numbers
SUB R2, R2, SP ;to perform the operations
LSR R2, R2, #2
MOV R10, #0;Bool activated if we are dealing with floats
;Switch operator
;unary operator
CMP R2, #2 ;Assert remaining numbers >= 1
ASSERT N=0;There is no remaining numbers to perform the operation
POP {R3, R4}
;R3 : type of first operand
;R4 : first operand
CMP R0, #0x7E; case ~
BEQ bitwise_not_op
CMP R0, #0x21; case !
BEQ not_op
LDR R6, =0x2B2B
CMP R0, R6; case ++
BEQ increment_op
LDR R6, =0x2D2D
CMP R0, R6; case --
BEQ decrement_op
LDR R6, =0x616273
CMP R0, R6; case abs
BEQ abs_op
;binary operator
CMP R2, #4 ;Assert remaining numbers >= 2
ASSERT N=0;There is not enough remaining numbers to perform the operation
POP {R5, R6}
;R5 : type of second operand
;R6 : second operand
;Test if there is float operand
CMP R3, #0x66
MOVEQ R10, #1
CMP R5, #0x66
MOVEQ R10, #1
CMP R10, #1;Test if we are dealing with floats
BNE calculation_no_float
;If so we perform conversion
PUSH {R0}
CMP R3, #0x66;of first operand
MOVNE R0, R4
BLNE int_to_IEE_754
CMP R3, #0x66
MOVNE R4, R0
CMP R5, #0x66;of second operand
MOVNE R0, R6
BLNE int_to_IEE_754
CMP R5, #0x66
MOVNE R6, R0
POP {R0}
calculation_no_float
CMP R0, #0x2B; case +
BEQ addition_op
CMP R0, #0x2D; case -
BEQ subtraction_op
CMP R0, #0x2A; case *
BEQ multiplication_op
CMP R0, #0x2F; case /
BEQ quotient_op
CMP R0, #0x25; case %
BEQ remainder_op
CMP R0, #0x26; case &
BEQ and_op
CMP R0, #0x7C; case |
BEQ or_op
CMP R0, #0x5E; case ^
BEQ xor_op
CMP R0, #0x3E; case >
BEQ greater_op
CMP R0, #0x3C; case <
BEQ less_op
LDR R7, =0x2A2A
CMP R0, R7; case **
BEQ pow_op
LDR R7, =0x3C3C
CMP R0, R7; case <<
BEQ left_shift_op
LDR R7, =0x3E3E
CMP R0, R7; case >>
BEQ right_shift_op
LDR R7, =0x3E3D
CMP R0, R7; case >=
BEQ greater_equal_op
LDR R7, =0x3C3D
CMP R0, R7; case <=
BEQ less_equal_op
LDR R7, =0x3D3D
CMP R0, R7; case ==
BEQ equal_op
LDR R7, =0x213D
CMP R0, R7; case !=
BEQ not_equal_op
LDR R7, =0x2626
CMP R0, R7; case &&
BEQ and_logical_op
LDR R7, =0x7C7C
CMP R0, R7; case ||
BEQ or_logical_op
ASSERT Z=1;The operator is not a valid one
B break
addition_op
CMP R10, #0
BNE addition_op_float
ADD R0, R6, R4
B addition_op_end
addition_op_float
MOV R0, R6
MOV R1, R4
BL fadd
addition_op_end
PUSH {R0}
B break
subtraction_op
CMP R10, #0
BNE subtraction_op_float
SUB R0, R6, R4
B subtraction_op_end
subtraction_op_float
MOV R0, R6
MOV R1, R4
BL fsub
subtraction_op_end
PUSH {R0}
B break
multiplication_op
CMP R10, #0
BNE multiplication_op_float
MUL R0, R6, R4
B multiplication_op_end
multiplication_op_float
MOV R0, R6
MOV R1, R4
BL fmul
multiplication_op_end
PUSH {R0}
B break
quotient_op
CMP R10, #0
BNE division_op_float
MOV R0, R6
MOV R1, R4
BL division
B quotient_op_end
division_op_float
MOV R0, R6
MOV R1, R4
BL fdiv
quotient_op_end
PUSH {R0}
B break
remainder_op
ASSERT R10=0;You can't use this operator on floats
MOV R0, R6
MOV R1, R4
BL division
PUSH {R1}
B break
pow_op
ASSERT R10=0;You can't use this operator on floats
MOV R0, R6
MOV R1, R4
BL pow
PUSH {R0}
B break
and_op
ASSERT R10=0;You can't use this operator on floats
AND R0, R6, R4
PUSH {R0}
B break
or_op
ASSERT R10=0;You can't use this operator on floats
ORR R0, R6, R4
PUSH {R0}
B break
xor_op
ASSERT R10=0;You can't use this operator on floats
EOR R0, R6, R4
PUSH {R0}
B break
bitwise_not_op
CMP R3, #0x66
ASSERT Z=0;You can't use this operator on a float
MVN R0, R4
PUSH {R0}
B break
left_shift_op
ASSERT R10=0;You can't use this operator on floats
MOV R0, R6
MOV R1, R4
BL lsl
PUSH {R0}
B break
right_shift_op
ASSERT R10=0;You can't use this operator on floats
MOV R0, R6
MOV R1, R4
BL lsr
PUSH {R0}
B break
greater_op
CMP R10, #0
BNE greater_op_float
CMP R6, R4
MOVGT R0, #1