1 /**
2 * Assembly CTFE Helpers for 32-bit x86
3 * 
4 * Copyright:
5 * (C) 1999-2008 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.utils.asm_x86_32.asm_x86_32;
12 import std.conv : to;
13 import botan.constants;
14 
15 static if (BOTAN_HAS_DMD_X86_INLINE_ASM) {
16 
17     enum START_ASM = "asm pure nothrow {\n";
18     enum END_ASM = "}\n";
19 
20     /*
21     * General/Global Macros
22     */
23     enum ALIGN = "align 16;";
24 
25     /*
26     * Loop Control
27     */
28     string START_LOOP(string LABEL) {
29         return ALIGN ~ "\n" ~ LABEL  ~ "_LOOP:\n";
30     }
31 
32     string LOOP_UNTIL_EQ(string REG, int NUM, string LABEL) {
33         return "cmp  " ~ REG ~ ", " ~ IMM(NUM) ~ ";\njne " ~ LABEL ~ "_LOOP;\n";
34     }
35 
36     string LOOP_UNTIL_LT(REG, NUM, LABEL)() {
37         return "cmp " ~ REG ~ ", " ~ IMM(NUM) ~ ";\njge " ~ LABEL ~ "_LOOP;\n";
38     }
39 
40     /*
41      Conditional Jumps
42     */
43     string JUMP_IF_ZERO(string REG, string LABEL)() {
44         return "cmp " ~ REG ~ ", " ~ IMM(0) ~ ";
45                 jz " ~ LABEL ~ ";\n";
46     }
47 
48     string JUMP_IF_LT(string REG, int NUM, string LABEL) {
49         return "cmp " ~ REG ~ ", " ~ IMM(NUM) ~ ";\njl " ~ LABEL ~ ";\n";
50     }
51 
52     /*
53     * Register Names
54     */
55     enum EAX = "EAX";
56     enum EBX = "EBX";
57     enum ECX = "ECX";
58     enum EDX = "EDX";
59     enum EBP = "EBP";
60     enum EDI = "EDI";
61     enum ESI = "ESI";
62     enum ESP = "ESP";
63 
64     /*
65     * Memory Access Operations
66     */
67     string ARRAY4(string REG, int NUM) { return "[" ~ REG ~ " + 4*" ~ NUM.to!string ~ "]"; }
68     string ARRAY4_INDIRECT(string BASE, string OFFSET, int NUM) { return "4*" ~ NUM.to!string ~ "[" ~ BASE ~ " + " ~ OFFSET ~ " * 4]"; }
69     string ARG(int PUSHED, int NUM) { return "4*" ~ PUSHED.to!string ~ " + " ~ ARRAY4(ESP, NUM); }
70 
71     string ASSIGN(string TO, string FROM) { return "mov " ~ TO ~ ", " ~ FROM ~ ";\n"; }
72     string ASSIGN_BYTE(string TO, string FROM) { return "mov " ~ TO ~ ", " ~ FROM ~ ";\n"; }
73 
74     string PUSH(string REG) { return "push " ~ REG ~ ";\n"; }
75     string POP(string REG) { return "pop " ~ REG ~ ";\n"; }
76 
77     string SPILL_REGS() {
78         return PUSH(EBP) ~ PUSH(EDI) ~ PUSH(ESI) ~ PUSH(EBX);
79     }
80     
81     string RESTORE_REGS() {
82         return POP(EBX) ~ POP(ESI) ~ POP(EDI) ~ POP(EBP);
83     }
84 
85     /*
86     * ALU Operations
87     */
88     string IMM(int VAL) { return VAL.to!string; }
89 
90     string ADD(string TO, string FROM) { return "add " ~ TO ~ ", " ~ FROM ~ ";\n"; }
91     string ADD_IMM(string TO, int NUM) { return ADD(TO, IMM(NUM)); }
92     string ADD_W_CARRY(string TO1, string TO2, string FROM) { return "add " ~ TO1 ~ ", " ~ FROM ~ "; adc " ~ TO2 ~ ", " ~ IMM(0) ~ ";\n"; }
93     string SUB_IMM(string TO, int NUM) { return "sub " ~ TO ~ ", " ~ IMM(NUM) ~ ";\n"; }
94     string ADD2_IMM(string TO, string FROM, int NUM) { return "lea "  ~ TO ~ ", " ~ NUM.to!string ~ "[" ~ FROM ~ "];\n"; }
95     string ADD3_IMM(string TO, string FROM, int NUM) { return "lea " ~ TO ~ ", " ~ NUM.to!string ~ "[" ~ TO ~ "+" ~ FROM ~ "];\n"; }
96     string MUL(string REG) { return "mul " ~ REG ~ ";\n"; }
97 
98     string SHL_IMM(string REG, int SHIFT) { return "shl " ~ REG ~ ", " ~ IMM(SHIFT) ~ ";\n"; }
99     string SHR_IMM(string REG, int SHIFT) { return "shr " ~ REG ~ ", " ~ IMM(SHIFT) ~ ";\n"; }
100     string SHL2_3(string TO, string FROM) { return "lea " ~ TO ~ ", [" ~ FROM ~ "*8];\n"; }
101 
102     string XOR(string TO, string FROM) { return "xor " ~ TO ~ ", " ~ FROM ~ ";\n"; }
103     string AND(string TO, string FROM) { return "and " ~ TO ~ ", " ~ FROM ~ ";\n"; }
104     string OR(string TO, string FROM) { return "or " ~ TO ~ ", " ~ FROM ~ ";\n"; }
105     string NOT(string REG) { return "not " ~ REG ~ ";\n"; }
106     string ZEROIZE(string REG) { return XOR(REG, REG); }
107 
108     string ROTL_IMM(string REG, int NUM) { return "rol " ~ REG ~ ", " ~ IMM(NUM) ~ ";\n"; }
109     string ROTR_IMM(string REG, int NUM) { return "ror " ~ REG ~ ", " ~ IMM(NUM) ~ ";\n"; }
110     string BSWAP(string REG) { return "bswap " ~ REG ~ ";\n"; }
111 
112 }
113 else {
114     version(GNU) {
115         enum START_ASM = "asm pure nothrow {";
116     }
117     version(none) {
118         enum START_ASM = "__asm pure nothrow {";
119     }
120     enum END_ASM = "::}";
121 
122 
123     /*
124     * General/Global Macros
125     */
126     enum ALIGN = ".p2align 4,,15\n";
127     
128     /*
129     * Loop Control
130     */
131     string START_LOOP(string LABEL) {
132         return ALIGN ~ ";
133                 " ~ LABEL  ~ "_LOOP:";
134     }
135     
136     string LOOP_UNTIL_EQ(string REG, int NUM, string LABEL) {
137         return "cmpl  " ~ IMM(NUM) ~ ", " ~ REG ~ "\n"
138                 ~ "jne " ~ LABEL ~ "_LOOP\n";
139     }
140     
141     string LOOP_UNTIL_LT(REG, NUM, LABEL)() {
142         return "cmpl " ~ IMM(NUM) ~ ", " ~ REG ~ "\n"    
143                 ~ "jge " ~ LABEL ~ "_LOOP\n";
144     }
145     
146     /*
147      Conditional Jumps
148     */
149     string JUMP_IF_ZERO(string REG, string LABEL)() {
150         return "cmpl " ~ IMM(0) ~ ", " ~ REG ~ "\n"
151                 ~ "jz " ~ LABEL ~ "\n";
152     }
153     
154     string JUMP_IF_LT(string REG, int NUM, string LABEL) {
155         return "cmpl " ~ IMM(NUM) ~ ", " ~ REG ~ "\n"
156                 ~ "jl " ~ LABEL ~ "\n";
157     }
158     
159     /*
160     * Register Names
161     */
162     enum EAX = "%%eax";
163     enum EBX = "%%ebx";
164     enum ECX = "%%ecx";
165     enum EDX = "%%edx";
166     enum EBP = "%%ebp";
167     enum EDI = "%%edi";
168     enum ESI = "%%esi";
169     enum ESP = "%%esp";
170     
171     /*
172     * Memory Access Operations
173     */
174     string ARRAY4(string REG, int NUM) { return "4*(" ~ NUM.to!string ~ ")(" ~ REG ~ ")"; }
175     string ARRAY4_INDIRECT(string BASE, string OFFSET, int NUM) { return "4*(" ~ NUM.to!string ~ ")(" ~ BASE ~ ", " ~ OFFSET ~ ", 4)"; }
176     string ARG(int PUSHED, int NUM) { return "4*(" ~ PUSHED.to!string ~ ") + " ~ ARRAY4(ESP, NUM); }
177     
178     string ASSIGN(string TO, string FROM) { return "movl " ~ FROM ~ ", " ~ TO ~ "\n"; }
179     string ASSIGN_BYTE(string TO, string FROM) { return "movzbl " ~ FROM ~ ", " ~ TO ~ "\n"; }
180     
181     string PUSH(string REG) { return "pushl" ~ REG ~ "\n"; }
182     string POP(string REG) { return "popl" ~ REG ~ "\n"; }
183     
184     string SPILL_REGS() {
185         return PUSH(EBP) ~ "
186                " ~ PUSH(EDI) ~ "
187                " ~ PUSH(ESI) ~ "
188                " ~ PUSH(EBX);
189     }
190     
191     string RESTORE_REGS() {
192         return POP(EBX) ~ "
193                " ~ POP(ESI) ~ "
194                " ~ POP(EDI) ~ "
195                " ~ POP(EBP);
196     }
197     
198     /*
199     * ALU Operations
200     */
201     string IMM(int VAL) { return VAL.to!string; }
202     
203     string ADD(string TO, string FROM) { return "addl " ~ FROM ~ ", " ~ TO ~ "\n"; }
204     string ADD_IMM(string TO, int NUM) { return ADD(TO, IMM(NUM)); }
205     string ADD_W_CARRY(string TO1, string TO2, string FROM) { return "addl " ~ FROM ~ ", " ~ TO1 ~ "\n"
206                                                                      ~ "adcl " ~ IMM(0) ~ ", " ~ TO2 ~ "\n"; }
207     string SUB_IMM(string TO, int NUM) { return "subl " ~ IMM(NUM) ~ ", " ~ TO ~ "\n"; }
208     string ADD2_IMM(string TO, string FROM, int NUM) { return "leal "  ~ NUM.to!string ~ "(" ~ FROM ~ ")" ~ ", " ~ TO ~ "\n"; }
209     string ADD3_IMM(string TO, string FROM, int NUM) { return "leal " ~ NUM.to!string ~ "(" ~ TO ~ ", " ~ FROM ~ ", 1), " ~ TO ~ "\n"; }
210     string MUL(string REG) { return "mull " ~ REG ~ "\n"; }
211     
212     string SHL_IMM(string REG, int SHIFT) { return "shll " ~ IMM(SHIFT) ~ ", " ~ REG ~ "\n"; }
213     string SHR_IMM(string REG, int SHIFT) { return "shrl " ~ IMM(SHIFT) ~ ", " ~ REG ~ "\n"; }
214     string SHL2_3(string TO, string FROM) { return "leal 0(," ~ FROM ~ ", 8), " ~ TO ~ "\n"; }
215     
216     string XOR(string TO, string FROM) { return "xorl " ~ FROM ~ ", " ~ TO ~ "\n"; }
217     string AND(string TO, string FROM) { return "andl " ~ FROM ~ ", " ~ TO ~ "\n"; }
218     string OR(string TO, string FROM) { return "orl " ~ FROM ~ ", " ~ TO ~ "\n"; }
219     string NOT(string REG) { return "notl " ~ REG ~ "\n"; }
220     string ZEROIZE(string REG) { return XOR(REG, REG); }
221     
222     string ROTL_IMM(string REG, int NUM) { return "roll " ~ IMM(NUM) ~ "," ~ REG ~ "\n"; }
223     string ROTR_IMM(string REG, int NUM) { return "rorl " ~ IMM(NUM) ~ "," ~ REG ~ "\n"; }
224     string BSWAP(string REG) { return "bswapl " ~ REG ~ "\n"; }
225 }