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 }