1#include <stdlib.h>2#include <string.h>34#include <scc/mach.h>5#include <scc/scc.h>67#include "../as.h"8#include "proc.h"910#define addrbyte(mod, reg, rm) ((mod) << 6 | (reg) << 3 | (rm))1112/*13 * This implementation is based in:14 * - x86 Opcode Structure and Instruction Overview - Fraunhofer-Institut15 * fÜr kommunikation, informationsverarbeitung und ergonomie fkie.16 * - Intel® 64 and IA-32 Architectures Software Developer’s Manual.17 * - Encoding Real x86 Instructions - CIS-77 lectures.18 */19enum addr_mode {20 MEM_MODE = 0,21 MEM8_MODE = 1,22 MEM16_MODE = 2,23 REG_MODE = 3,24};2526static int27getclass(Node *np)28{29 if (np->addr != AREG)30 return 0;3132 switch (np->sym->value) {33 case AREG_AL:34 case AREG_AH:35 case AREG_BL:36 case AREG_BH:37 case AREG_CL:38 case AREG_CH:39 case AREG_DL:40 case AREG_DH:41 return R8CLASS;4243 case AREG_AX:44 case AREG_BX:45 case AREG_CX:46 case AREG_DX:47 case AREG_DI:48 case AREG_SI:49 case AREG_SP:50 case AREG_BP:51 return R16CLASS;5253 case AREG_CS:54 case AREG_DS:55 case AREG_SS:56 case AREG_ES:57 case AREG_FS:58 case AREG_GS:5960 case AREG_EFLAGS:61 case AREG_CF:62 case AREG_PF:63 case AREG_AF:64 case AREG_ZF:65 case AREG_SF:66 case AREG_TF:67 case AREG_IF:68 case AREG_DF:69 case AREG_OF:70 case AREG_IOPL:71 case AREG_NT:72 case AREG_RF:73 case AREG_VM:74 case AREG_AC:75 case AREG_VIF:76 case AREG_VIP:77 case AREG_ID:7879 case AREG_EAX:80 case AREG_RAX:8182 case AREG_EBX:83 case AREG_RBX:8485 case AREG_ECX:86 case AREG_RCX:8788 case AREG_EDX:89 case AREG_RDX:9091 case AREG_SIL:92 case AREG_ESI:93 case AREG_RSI:94 case AREG_DIL:95 case AREG_EDI:96 case AREG_RDI:9798 case AREG_SPL:99 case AREG_ESP:100 case AREG_RSP:101102 case AREG_BPL:103 case AREG_EBP:104 case AREG_RBP:105106 case AREG_R0:107 case AREG_MM0:108 case AREG_R1:109 case AREG_MM1:110 case AREG_R2:111 case AREG_MM2:112 case AREG_R3:113 case AREG_MM3:114 case AREG_R4:115 case AREG_MM4:116 case AREG_R5:117 case AREG_MM5:118 case AREG_R6:119 case AREG_MM6:120 case AREG_R7:121 case AREG_MM7:122123 case AREG_R8:124 case AREG_R8L:125 case AREG_R8W:126 case AREG_R9:127 case AREG_R9L:128 case AREG_R9W:129 case AREG_R10:130 case AREG_R10L:131 case AREG_R10W:132 case AREG_R11:133 case AREG_R11L:134 case AREG_R11W:135 case AREG_R12:136 case AREG_R12L:137 case AREG_R12W:138 case AREG_R13:139 case AREG_R13L:140 case AREG_R13W:141 case AREG_R14:142 case AREG_R14L:143 case AREG_R14W:144 case AREG_R15:145 case AREG_R15L:146 case AREG_R15W:147148 case AREG_XMM0:149 case AREG_XMM1:150 case AREG_XMM2:151 case AREG_XMM3:152 case AREG_XMM4:153 case AREG_XMM5:154 case AREG_XMM6:155 case AREG_XMM7:156 case AREG_XMM8:157 case AREG_XMM9:158 case AREG_XMM10:159 case AREG_XMM11:160 case AREG_XMM12:161 case AREG_XMM13:162 case AREG_XMM14:163 case AREG_XMM15:164165 case AREG_YMM0:166 case AREG_YMM1:167 case AREG_YMM2:168 case AREG_YMM3:169 case AREG_YMM4:170 case AREG_YMM5:171 case AREG_YMM6:172 case AREG_YMM7:173 case AREG_YMM8:174 case AREG_YMM9:175 case AREG_YMM10:176 case AREG_YMM11:177 case AREG_YMM12:178 case AREG_YMM13:179 case AREG_YMM14:180 case AREG_YMM15:181182 case AREG_MXCSR:183 return 0;184 default:185 abort();186 }187}188189int190match(Op *op, Node **args)191{192 unsigned char *p;193 int arg, class, rep, opt;194 Node *np;195196 if (!op->args)197 return args == NULL;198199 opt = rep = 0;200 for (p = op->args; arg = *p; ++p) {201 if (rep)202 --p;203 if ((np = *args++) == NULL)204 return (rep|opt) != 0;205206 switch (arg) {207 case AOPT:208 opt = 1;209 break;210 case AREP:211 rep = 1;212 break;213 case AREG_R8CLASS:214 class = R8CLASS;215 goto check_class;216 case AREG_R16CLASS:217 class = R16CLASS;218 check_class:219 if ((getclass(np) & class) == 0)220 return 0;221 break;222 case AIMM8:223 case AIMM16:224 case AIMM32:225 case AIMM64:226 if (np->addr != AIMM)227 return 0;228 if (toobig(np, arg))229 error("overflow in immediate operand");230 break;231 case ASYM:232 if (np->op != IDEN)233 return 0;234 break;235 case ADIRECT:236 case ASTR:237 if (np->addr != arg)238 return 0;239 break;240 default:241 abort();242 }243 }244245 return *args == NULL;246}247248Node *249moperand(void)250{251}252253static int254reg8toint(Node *np)255{256 switch (np->sym->value) {257 case AREG_AL: return 0;258 case AREG_CL: return 1;259 case AREG_DL: return 2;260 case AREG_BL: return 3;261 case AREG_AH: return 4;262 case AREG_CH: return 5;263 case AREG_DH: return 6;264 case AREG_BH: return 7;265 default: abort();266 }267}268269static int270reg16toint(Node *np)271{272 switch (np->sym->value) {273 case AREG_AX: return 0;274 case AREG_CX: return 1;275 case AREG_DX: return 2;276 case AREG_BX: return 3;277 case AREG_SP: return 4;278 case AREG_BP: return 5;279 case AREG_SI: return 6;280 case AREG_DI: return 7;281 default: abort();282 }283}284285static int286reg32toint(Node *np)287{288 switch (np->sym->value) {289 case AREG_EAX: return 0;290 case AREG_ECX: return 1;291 case AREG_EDX: return 2;292 case AREG_EBX: return 3;293 case AREG_ESP: return 4;294 case AREG_EBP: return 5;295 case AREG_ESI: return 6;296 case AREG_EDI: return 7;297 default: abort();298 }299}300301void302reg8_reg8(Op *op, Node **args)303{304 int src, dst;305 unsigned char buf[op->size];306307 src = reg8toint(args[0]);308 dst = reg8toint(args[1]);309 memcpy(buf, op->bytes, op->size - 1);310 buf[op->size - 1] = addrbyte(REG_MODE, src, dst);311 emit(buf, op->size);312}313314void315imm8_reg8(Op *op, Node **args)316{317 int src, dst;318 unsigned char buf[op->size];319320 src = (*args)->sym->value;321 dst = reg8toint(args[1]);322 memcpy(buf, op->bytes, op->size - 2);323 buf[op->size - 2] = addrbyte(REG_MODE, 0, dst);324 buf[op->size - 1] = src;325 emit(buf, op->size);326}327328329void330reg16_reg16(Op *op, Node **args)331{332 int src, dst;333 unsigned char buf[op->size];334335 src = reg16toint(args[0]);336 dst = reg16toint(args[1]);337 memcpy(buf, op->bytes, op->size - 1);338 buf[op->size - 1] = addrbyte(REG_MODE, src, dst);339 emit(buf, op->size);340}341342343void344reg32_reg32(Op *op, Node **args)345{346 int src, dst;347 unsigned char buf[op->size];348349 src = reg32toint(args[0]);350 dst = reg32toint(args[1]);351 memcpy(buf, op->bytes, op->size - 1);352 buf[op->size - 1] = addrbyte(REG_MODE, src, dst);353 emit(buf, op->size);354}