-
Notifications
You must be signed in to change notification settings - Fork 0
/
reduce.s
159 lines (150 loc) · 2.95 KB
/
reduce.s
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
.equ EXP, -8
.equ RESULT, -16
.equ LENGTH, -24
.equ NEXT, -32
.equ EXP_TYPE, 1
.equ CONST_TYPE, 2
.equ OPERATOR_TYPE, 3
.equ TYPE_OFFSET, 0
.equ VALUE_OFFSET, 8
.text
.globl reduce
.type reduce, @function
reduce:
pushq %rbp
movq %rsp, %rbp
subq $8, %rsp
movq %rdi, EXP(%rbp)
movq TYPE_OFFSET(%rdi), %rbx
cmpq $CONST_TYPE, %rbx
je const_type
cmpq $OPERATOR_TYPE, %rbx
je operator_type
jmp exp_type
finish:
addq $8, %rsp
leave
ret
operator_type:
call free
xor %rax, %rax
jmp finish
const_type:
movq VALUE_OFFSET(%rdi), %rax
pushq %rax
call free
popq %rax
jmp finish
exp_type:
subq $16, %rsp
call get_length
movq %rax, LENGTH(%rbp)
cmpq $1, %rax
je one_arg
cmpq $2, %rax
je two_args
jmp many_args
one_arg:
movq VALUE_OFFSET(%rdi), %rdi
movq (%rdi), %rdi
call reduce
movq %rax, RESULT(%rbp)
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
call free
movq EXP(%rbp), %rdi
call free
movq RESULT(%rbp), %rax
addq $16, %rsp
jmp finish
two_args:
movq $1, %rcx # set multiplier
movq VALUE_OFFSET(%rdi), %rdi
movq (%rdi), %rdi
movq VALUE_OFFSET(%rdi), %rdi
cmpq $'+, %rdi
je leave_multiplier_unchanged
movq $-1, %rcx
leave_multiplier_unchanged:
pushq %rcx
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
movq 8(%rdi), %rdi
call reduce
popq %rcx
imul %rcx, %rax
movq %rax, RESULT(%rbp)
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
movq (%rdi), %rdi
call free
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
call free
movq EXP(%rbp), %rdi
call free
movq RESULT(%rbp), %rax
addq $16, %rsp
jmp finish
many_args:
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
call get_next_operator
subq $8, %rsp
movq %rax, NEXT(%rbp) # save next operator
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
leaq (%rdi, %rax, 8), %rdi
subq $8, %rdi
movq (%rdi), %rdi
call reduce
pushq %rax # save left expretion result
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
movq NEXT(%rbp), %rax
leaq (%rdi, %rax, 8), %rdi
addq $8, %rdi
movq (%rdi), %rdi
call reduce
popq %rdi # left expretion
movq %rax, %rsi # right expretion
movq EXP(%rbp), %rax
movq VALUE_OFFSET(%rax), %rax
movq NEXT(%rbp), %rdx
leaq (%rax, %rdx, 8), %rdx
movq (%rdx), %rdx
movq VALUE_OFFSET(%rdx), %rdx # operator
call execute
movq %rax, RESULT(%rbp)
movq NEXT(%rbp), %rax
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
leaq (%rdi, %rax, 8), %rdi
movq (%rdi), %rdi
call free
movq $16, %rdi
call malloc
movq %rax, %rbx
movq NEXT(%rbp), %rax
decq %rax
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
movq %rbx, (%rdi, %rax, 8)
movq $CONST_TYPE, (%rbx)
movq RESULT(%rbp), %rax
movq %rax, VALUE_OFFSET(%rbx)
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
movq NEXT(%rbp), %rax
movq $0, (%rdi, %rax, 8)
incq %rax
movq $0, (%rdi, %rax, 8)
movq EXP(%rbp), %rdi
movq VALUE_OFFSET(%rdi), %rdi
movq NEXT(%rbp), %rsi
movq LENGTH(%rbp), %rdx
call shift_entries
movq EXP(%rbp), %rdi
call reduce
addq $24, %rsp
jmp finish