x86_64.om (48315B)
1 enum { 2 R_RAX, 3 R_RCX, 4 R_RDX, 5 R_RBX, 6 R_RSP, 7 R_RBP, 8 R_RSI, 9 R_RDI, 10 R_R8, 11 R_R9, 12 R_R10, 13 R_R11, 14 R_R12, 15 R_R13, 16 R_R14, 17 R_R15, 18 R_RIP, 19 20 R_ES = 0, 21 R_CS = 1, 22 R_SS = 2, 23 R_DS = 3, 24 R_FS = 4, 25 R_GS = 5, 26 27 R_CR0 = 0, 28 R_CR1 = 1, 29 R_CR2 = 2, 30 R_CR3 = 3, 31 R_CR4 = 4, 32 R_CR5 = 5, 33 R_CR6 = 6, 34 R_CR7 = 7, 35 } 36 37 enum { 38 CC_O = 0x00, 39 CC_NO = 0x01, 40 CC_B = 0x02, 41 CC_AE = 0x03, 42 CC_E = 0x04, 43 CC_NE = 0x05, 44 CC_BE = 0x06, 45 CC_A = 0x07, 46 CC_S = 0x08, 47 CC_NS = 0x09, 48 CC_P = 0x0a, 49 CC_NP = 0x0b, 50 CC_L = 0x0c, 51 CC_GE = 0x0d, 52 CC_LE = 0x0e, 53 CC_G = 0x0f, 54 } 55 56 enum { 57 OP_GS = 0x65, 58 OP_OS = 0x66, 59 60 OP_CLD = 0xfc, 61 OP_CLI = 0xfa, 62 OP_STI = 0xfb, 63 OP_CPUID = 0x0fa2, 64 OP_IN = 0xec, 65 OP_IND = 0xed, 66 OP_OUT = 0xee, 67 OP_OUTD = 0xef, 68 OP_HLT = 0xf4, 69 OP_NOP = 0x90, 70 OP_WBINVD = 0x0f09, 71 OP_UD2 = 0x0f0b, 72 73 OP_INVLPGM = 0x070f01, 74 OP_LLDM = 0x020f00, 75 OP_LTRM = 0x030f00, 76 77 OP_WRSR = 0x8e, 78 OP_RDSR = 0x8c, 79 80 OP_RET = 0xc3, 81 OP_CALL = 0xe8, 82 OP_JMP = 0xe9, 83 OP_JCC = 0x0f80, 84 OP_SETCC = 0x0f90, 85 86 OP_PUSHF = 0x9c, 87 OP_POPF = 0x9d, 88 OP_IRET = 0xcf, 89 OP_IRETQ = 0x48cf, 90 OP_WRMSR = 0x0f30, 91 OP_RDMSR = 0x0f32, 92 OP_RDCRR = 0x0f20, 93 OP_WRCRR = 0x0f22, 94 OP_LGDTM = 0x020f01, 95 OP_LIDTM = 0x030f01, 96 OP_LLDTM = 0x020f00, 97 98 OP_ICALLM = 0x0200ff, 99 100 OP_NOTM = 0x0200f7, 101 OP_NEGM = 0x0300f7, 102 103 OP_ANDRM = 0x23, 104 OP_ORRM = 0x0b, 105 OP_CMPRM = 0x3b, 106 OP_TESTRM = 0x85, 107 OP_SUBRM = 0x2b, 108 OP_ADDRM = 0x03, 109 OP_ADCRM = 0x13, 110 OP_XORRM = 0x33, 111 112 OP_ANDI = 0x040081, 113 OP_ADDI = 0x000081, 114 OP_SUBI = 0x050081, 115 OP_ORI = 0x010081, 116 OP_CMPI = 0x070081, 117 118 OP_RDRAND = 0x060fc7, 119 120 OP_IMULM = 0x0400f7, 121 OP_IDIVM = 0x0700f7, 122 OP_SHLM = 0x0400d3, 123 OP_SHRM = 0x0500d3, 124 125 OP_PUSHR = 0x50, 126 127 OP_POPR = 0x58, 128 129 OP_MOVI = 0x00c7, 130 OP_MOVABS = 0xb8, 131 132 OP_SYSCALL = 0x0f05, 133 OP_SYSRET = 0x0f07, 134 135 OP_LEA = 0x8d, 136 OP_LOAD = 0x8b, 137 OP_LOADB = 0x8a, 138 OP_LOAD16 = 0x668a, 139 OP_STOREB = 0x88, 140 OP_STORE = 0x89, 141 OP_STORE16 = 0x6689, 142 OP_MOVE = 0x8b, 143 } 144 145 func x86_64_rex(a: *assembler, op: int, r: int, i: int, b: int) { 146 var w: int; 147 if a.bits32 { 148 return; 149 } 150 w = 0x08; 151 if op == OP_LOADB || op == OP_STOREB { 152 w = 0; 153 if r < 8 && i < 8 && b < 8 { 154 return; 155 } 156 } 157 as_emit(a, 0x40 + w + ((r >> 1) & 4) + ((i >> 2) & 2) + ((b >> 3) & 1)); 158 } 159 160 func x86_64_op(a: *assembler, op: int) { 161 if op > 0xff { 162 as_emit(a, op >> 8); 163 as_emit(a, op); 164 } else { 165 as_emit(a, op); 166 } 167 } 168 169 // op + r 170 func x86_64_opr(a: *assembler, op: int, r: int) { 171 if r < 0 || r > 15 { 172 die("invalid reg"); 173 } 174 if (op != OP_PUSHR && op != OP_POPR) || r > 7 { 175 x86_64_rex(a, op, r, 0, 0); 176 } 177 x86_64_op(a, op + (r & 7)); 178 } 179 180 func x86_64_opri64(a: *assembler, op: int, r: int, x: int) { 181 if op != OP_MOVABS { 182 die("only movabs"); 183 } 184 x86_64_opr(a, op, r); 185 as_emit(a, x); 186 as_emit(a, x >> 8); 187 as_emit(a, x >> 16); 188 as_emit(a, x >> 24); 189 as_emit(a, x >> 32); 190 as_emit(a, x >> 40); 191 as_emit(a, x >> 48); 192 as_emit(a, x >> 56); 193 } 194 195 // modrm 196 func x86_64_modrr(a: *assembler, op: int, r: int, b: int) { 197 if r < 0 || r > 15 || b < 0 || b > 15 { 198 die("invalid reg"); 199 } 200 if (op != (OP_ICALLM & 0xffff) && (op & -16) != OP_SETCC) || b >= 8 { 201 x86_64_rex(a, op, r, 0, b); 202 } 203 x86_64_op(a, op); 204 as_emit(a, 0xc0 + ((r << 3) & 0x38) + (b & 0x07)); 205 } 206 207 // modrm /op 208 func x86_64_modr(a: *assembler, op: int, b: int) { 209 x86_64_modrr(a, op & 0xffff, op >> 16, b); 210 } 211 212 // modrm + disp 213 func x86_64_modra(a: *assembler, op: int, r: int, d: int) { 214 x86_64_rex(a, op, r, 0, 0); 215 x86_64_op(a, op); 216 as_emit(a, ((r << 3) & 0x38) + R_RSP); 217 as_emit(a, (R_RSP << 3) + R_RBP); 218 as_emit(a, d); 219 as_emit(a, d >> 8); 220 as_emit(a, d >> 16); 221 as_emit(a, d >> 24); 222 } 223 224 // modrm + sib + disp 225 func x86_64_modrm(a: *assembler, op: int, r: int, b: int, i: int, s: int, d: int) { 226 var sib: int; 227 var mod: int; 228 var rm: int; 229 var dw: int; 230 231 if r < 0 || r > 15 { 232 die("invalid reg"); 233 } 234 235 rm = (r << 3) & 0x38; 236 237 if d != 0 { 238 if d >= -128 && d <= 127 { 239 mod = 1; 240 dw = 1; 241 } else { 242 mod = 2; 243 dw = 4; 244 } 245 } else { 246 mod = 0; 247 dw = 0; 248 } 249 250 if mod == 0 { 251 if b < 0 || b > 16 { 252 die("invalid reg"); 253 } 254 255 if s { 256 if b == R_RIP { 257 die("invalid base"); 258 } 259 260 if i == R_RSP { 261 die("invalid index"); 262 } 263 264 rm = rm + R_RSP; 265 } else { 266 if i != 0 { 267 die("invalid index"); 268 } 269 270 if b == R_RIP { 271 mod = 0; 272 dw = 4; 273 rm = rm + R_RBP; 274 } else if b == R_RSP || b == R_R12 { 275 s = 1; 276 i = R_RSP; 277 rm = rm + R_RSP; 278 } else if b == R_RBP || b == R_R13 { 279 mod = 1; 280 dw = 1; 281 rm = rm + R_RBP; 282 } else { 283 rm = rm + (b & 7); 284 } 285 } 286 } else { 287 if b < 0 || b > 16 || i < 0 || i > 15 { 288 die("invalid reg"); 289 } 290 291 if s { 292 if b == R_RIP { 293 die("invalid base"); 294 } 295 296 if i == R_RSP { 297 die("invalid index"); 298 } 299 300 rm = rm + R_RSP; 301 } else { 302 if i != 0 { 303 die("invalid index"); 304 } 305 306 if b == R_RIP { 307 mod = 0; 308 dw = 4; 309 rm = rm + R_RBP; 310 } else if b == R_RSP || b == R_R12 { 311 s = 1; 312 i = R_RSP; 313 rm = rm + R_RSP; 314 } else { 315 rm = rm + (b & 7); 316 } 317 } 318 } 319 320 x86_64_rex(a, op, r, i, b); 321 x86_64_op(a, op); 322 as_emit(a, (mod << 6) + rm); 323 324 if s { 325 sib = ((i << 3) & 0x38) + (b & 0x07); 326 if s == 2 { 327 sib = sib + 0x40; 328 } else if s == 4 { 329 sib = sib + 0x80; 330 } else if s == 8 { 331 sib = sib + 0xc0; 332 } else if s != 1 { 333 die("invalid scale"); 334 } 335 as_emit(a, sib); 336 } 337 338 if dw == 1 { 339 as_emit(a, d); 340 } else if dw == 4 { 341 as_emit(a, d); 342 as_emit(a, d >> 8); 343 as_emit(a, d >> 16); 344 as_emit(a, d >> 24); 345 } 346 } 347 348 // modrm /op 349 func x86_64_modm(a: *assembler, op: int, b: int, i: int, s: int, d: int) { 350 x86_64_modrm(a, op & 0xffff, op >> 16, b, i, s, d); 351 } 352 353 func x86_64_modri(a: *assembler, op: int, r: int, x: int) { 354 if x < -(1 << 31) || x >= (1 << 31) { 355 die("immediate too large"); 356 } 357 x86_64_modrr(a, op & 0xffff, op >> 16, r); 358 as_emit(a, x); 359 as_emit(a, x >> 8); 360 as_emit(a, x >> 16); 361 as_emit(a, x >> 24); 362 } 363 364 func x86_64_jmp(a: *assembler, op: int, l: *label) { 365 reserve(a, 16); 366 x86_64_op(a, op); 367 as_emit(a, 0); 368 as_emit(a, 0); 369 as_emit(a, 0); 370 as_emit(a, 0); 371 addfixup(a, l, FIXUP_DISP32); 372 } 373 374 func x86_64_ssr(c: *compiler) { 375 var d: *decl; 376 var v: *decl; 377 378 v = find(c, "global", "_save", 0); 379 if (!v || !v.member_defined) { 380 cdie(c, "no _save"); 381 } 382 383 // Save the current stack 384 as_emit(c.s, OP_GS); 385 x86_64_modra(c.s, OP_STORE, R_RSP, v.member_offset); 386 387 v = find(c, "global", "curtask", 0); 388 if (!v || !v.member_defined) { 389 cdie(c, "no global.curtask"); 390 } 391 392 // Load the current task 393 as_emit(c.s, OP_GS); 394 x86_64_modra(c.s, OP_LOAD, R_RSP, v.member_offset); 395 396 v = find(c, "task", "stack", 0); 397 if (!v || !v.member_defined) { 398 cdie(c, "no task.stack"); 399 } 400 401 // Load the kernel stack but reserve some space for the regs struct 402 x86_64_modrm(c.s, OP_LOAD, R_RSP, R_RSP, 0, 0, v.member_offset); 403 x86_64_modri(c.s, OP_ADDI, R_RSP, 4096 - 176); 404 405 // Save general purpose registers 406 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 0); 407 x86_64_modrm(c.s, OP_STORE, R_RDX, R_RSP, 0, 0, 16); 408 x86_64_modrm(c.s, OP_STORE, R_RBX, R_RSP, 0, 0, 24); 409 x86_64_modrm(c.s, OP_STORE, R_RBP, R_RSP, 0, 0, 40); 410 x86_64_modrm(c.s, OP_STORE, R_RSI, R_RSP, 0, 0, 48); 411 x86_64_modrm(c.s, OP_STORE, R_RDI, R_RSP, 0, 0, 56); 412 x86_64_modrm(c.s, OP_STORE, R_R8, R_RSP, 0, 0, 64); 413 x86_64_modrm(c.s, OP_STORE, R_R9, R_RSP, 0, 0, 72); 414 x86_64_modrm(c.s, OP_STORE, R_R10, R_RSP, 0, 0, 80); 415 x86_64_modrm(c.s, OP_STORE, R_R12, R_RSP, 0, 0, 96); 416 x86_64_modrm(c.s, OP_STORE, R_R13, R_RSP, 0, 0, 104); 417 x86_64_modrm(c.s, OP_STORE, R_R14, R_RSP, 0, 0, 112); 418 x86_64_modrm(c.s, OP_STORE, R_R15, R_RSP, 0, 0, 120); 419 x86_64_modrm(c.s, OP_STORE, R_RCX, R_RSP, 0, 0, 128); 420 x86_64_modrm(c.s, OP_STORE, R_R11, R_RSP, 0, 0, 136); 421 422 // Clear rcx, r11, trap, err 423 x86_64_modrr(c.s, OP_XORRM, R_RAX, R_RAX); 424 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 8); 425 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 88); 426 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 160); 427 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 168); 428 429 // Save cs and ds 430 x86_64_modri(c.s, OP_MOVI, R_RAX, 43); 431 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 144); 432 x86_64_modri(c.s, OP_MOVI, R_RAX, 35); 433 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 152); 434 435 v = find(c, "global", "_save", 0); 436 if (!v || !v.member_defined) { 437 cdie(c, "no _save"); 438 } 439 440 // Save the saved stack and switch back 441 as_emit(c.s, OP_GS); 442 x86_64_modra(c.s, OP_LOAD, R_RAX, v.member_offset); 443 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RSP, 0, 0, 32); 444 x86_64_modrr(c.s, OP_MOVE, R_RAX, R_RSP); 445 446 // Create a frame 447 x86_64_modrr(c.s, OP_XORRM, R_RBP, R_RBP); 448 x86_64_opr(c.s, OP_PUSHR, R_RBP); 449 x86_64_opr(c.s, OP_PUSHR, R_RBP); 450 x86_64_modrr(c.s, OP_MOVE, R_RBP, R_RSP); 451 452 x86_64_modrr(c.s, OP_MOVE, R_RDI, R_RAX); 453 454 // Call _ssr 455 d = find(c, "_ssr", nil, 1); 456 if (d.func_defined && d.func_label.fixed) { 457 x86_64_jmp(c.s, OP_CALL, d.func_label); 458 } 459 460 x86_64_op(c.s, OP_CLI); 461 462 // Delete the frame 463 x86_64_modri(c.s, OP_ADDI, R_RSP, 2 * 8); 464 465 // Restore the old registers 466 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSP, 0, 0, 0); 467 x86_64_modrm(c.s, OP_LOAD, R_RDX, R_RSP, 0, 0, 16); 468 x86_64_modrm(c.s, OP_LOAD, R_RBX, R_RSP, 0, 0, 24); 469 x86_64_modrm(c.s, OP_LOAD, R_RBP, R_RSP, 0, 0, 40); 470 x86_64_modrm(c.s, OP_LOAD, R_RSI, R_RSP, 0, 0, 48); 471 x86_64_modrm(c.s, OP_LOAD, R_RDI, R_RSP, 0, 0, 56); 472 x86_64_modrm(c.s, OP_LOAD, R_R8, R_RSP, 0, 0, 64); 473 x86_64_modrm(c.s, OP_LOAD, R_R9, R_RSP, 0, 0, 72); 474 x86_64_modrm(c.s, OP_LOAD, R_R10, R_RSP, 0, 0, 80); 475 x86_64_modrm(c.s, OP_LOAD, R_R12, R_RSP, 0, 0, 96); 476 x86_64_modrm(c.s, OP_LOAD, R_R13, R_RSP, 0, 0, 104); 477 x86_64_modrm(c.s, OP_LOAD, R_R14, R_RSP, 0, 0, 112); 478 x86_64_modrm(c.s, OP_LOAD, R_R15, R_RSP, 0, 0, 120); 479 480 x86_64_modrm(c.s, OP_LOAD, R_RCX, R_RSP, 0, 0, 128); 481 x86_64_modrm(c.s, OP_LOAD, R_R11, R_RSP, 0, 0, 136); 482 483 x86_64_modrm(c.s, OP_LOAD, R_RSP, R_RSP, 0, 0, 32); 484 485 // Return to the user 486 x86_64_rex(c.s, OP_SYSRET, 0, 0, 0); 487 x86_64_op(c.s, OP_SYSRET); 488 } 489 490 func x86_64_isr(c: *compiler) { 491 var d: *decl; 492 var out: *label; 493 var i: int; 494 495 out = mklabel(c.s); 496 497 i = 0; 498 loop { 499 if i == 256 { 500 break; 501 } 502 reserve(c.s, 16); 503 504 if i == 8 || i == 10 || i == 11 || i == 12 505 || i == 13 || i == 14 || i == 17 || i == 21 506 || i == 29 || i == 30 { 507 // nop 508 as_emit(c.s, 0x90); 509 as_emit(c.s, 0x90); 510 } else { 511 // push 0 512 as_emit(c.s, 0x6a); 513 as_emit(c.s, 0x00); 514 } 515 516 // push i 517 as_emit(c.s, 0x68); 518 as_emit(c.s, i); 519 as_emit(c.s, 0x00); 520 as_emit(c.s, 0x00); 521 as_emit(c.s, 0x00); 522 523 // jmp out 524 as_emit(c.s, 0xe9); 525 as_emit(c.s, 0x00); 526 as_emit(c.s, 0x00); 527 as_emit(c.s, 0x00); 528 as_emit(c.s, 0x00); 529 addfixup(c.s, out, FIXUP_DISP32); 530 531 // Align to 16 532 as_emit(c.s, 0x90); 533 as_emit(c.s, 0x90); 534 as_emit(c.s, 0x90); 535 as_emit(c.s, 0x90); 536 537 i = i + 1; 538 } 539 540 fixup_label(c.s, out); 541 542 // Allocate a regs struct 543 x86_64_modri(c.s, OP_SUBI, R_RSP, 176); 544 545 // Save rbp and use it as the regs pointer 546 x86_64_modrm(c.s, OP_STORE, R_RBP, R_RSP, 0, 0, 40); 547 x86_64_modrr(c.s, OP_MOVE, R_RBP, R_RSP); 548 549 // Save general purpose registers 550 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 0); 551 x86_64_modrm(c.s, OP_STORE, R_RCX, R_RBP, 0, 0, 8); 552 x86_64_modrm(c.s, OP_STORE, R_RDX, R_RBP, 0, 0, 16); 553 x86_64_modrm(c.s, OP_STORE, R_RBX, R_RBP, 0, 0, 24); 554 x86_64_modrm(c.s, OP_STORE, R_RSI, R_RBP, 0, 0, 48); 555 x86_64_modrm(c.s, OP_STORE, R_RDI, R_RBP, 0, 0, 56); 556 x86_64_modrm(c.s, OP_STORE, R_R8, R_RBP, 0, 0, 64); 557 x86_64_modrm(c.s, OP_STORE, R_R9, R_RBP, 0, 0, 72); 558 x86_64_modrm(c.s, OP_STORE, R_R10, R_RBP, 0, 0, 80); 559 x86_64_modrm(c.s, OP_STORE, R_R11, R_RBP, 0, 0, 88); 560 x86_64_modrm(c.s, OP_STORE, R_R12, R_RBP, 0, 0, 96); 561 x86_64_modrm(c.s, OP_STORE, R_R13, R_RBP, 0, 0, 104); 562 x86_64_modrm(c.s, OP_STORE, R_R14, R_RBP, 0, 0, 112); 563 x86_64_modrm(c.s, OP_STORE, R_R15, R_RBP, 0, 0, 120); 564 565 // trap 566 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 0); 567 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 160); 568 // err 569 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 8); 570 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 168); 571 // rip 572 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 16); 573 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 128); 574 // cs 575 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 24); 576 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 144); 577 // flags 578 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 32); 579 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 136); 580 // rsp 581 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 40); 582 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 32); 583 // ss 584 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 176 + 48); 585 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 152); 586 587 // Call _isr 588 x86_64_modrr(c.s, OP_MOVE, R_RDI, R_RBP); 589 d = find(c, "_isr", nil, 1); 590 if (d.func_defined && d.func_label.fixed) { 591 x86_64_jmp(c.s, OP_CALL, d.func_label); 592 } 593 594 // rip 595 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 128); 596 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 176 + 16); 597 // cs 598 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 144); 599 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 176 + 24); 600 // flags 601 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 136); 602 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 176 + 32); 603 // rsp 604 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 32); 605 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 176 + 40); 606 // ss 607 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 152); 608 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RBP, 0, 0, 176 + 48); 609 610 // Restore general purpose registers 611 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 0); 612 x86_64_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 8); 613 x86_64_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); 614 x86_64_modrm(c.s, OP_LOAD, R_RBX, R_RBP, 0, 0, 24); 615 x86_64_modrm(c.s, OP_LOAD, R_RSI, R_RBP, 0, 0, 48); 616 x86_64_modrm(c.s, OP_LOAD, R_RDI, R_RBP, 0, 0, 56); 617 x86_64_modrm(c.s, OP_LOAD, R_R8, R_RBP, 0, 0, 64); 618 x86_64_modrm(c.s, OP_LOAD, R_R9, R_RBP, 0, 0, 72); 619 x86_64_modrm(c.s, OP_LOAD, R_R10, R_RBP, 0, 0, 80); 620 x86_64_modrm(c.s, OP_LOAD, R_R11, R_RBP, 0, 0, 88); 621 x86_64_modrm(c.s, OP_LOAD, R_R12, R_RBP, 0, 0, 96); 622 x86_64_modrm(c.s, OP_LOAD, R_R13, R_RBP, 0, 0, 104); 623 x86_64_modrm(c.s, OP_LOAD, R_R14, R_RBP, 0, 0, 112); 624 x86_64_modrm(c.s, OP_LOAD, R_R15, R_RBP, 0, 0, 120); 625 626 // Restore rbp 627 x86_64_modrm(c.s, OP_LOAD, R_RBP, R_RBP, 0, 0, 40); 628 629 // Clean up regs + trap + err 630 x86_64_modri(c.s, OP_ADDI, R_RSP, 176 + 2 * 8); 631 632 x86_64_op(c.s, OP_IRETQ); 633 } 634 635 func x86_64_builtin(c: *compiler) { 636 var d: *decl; 637 638 d = find(c, "syscall", nil, 1); 639 if (d.func_defined && !d.func_label.fixed) { 640 fixup_label(c.s, d.func_label); 641 add_symbol(c.s, d.name, d.func_label); 642 x86_64_modrr(c.s, OP_MOVE, R_RAX, R_RDI); 643 x86_64_modrr(c.s, OP_MOVE, R_RDI, R_RSI); 644 x86_64_modrr(c.s, OP_MOVE, R_RSI, R_RDX); 645 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RCX); 646 x86_64_modrr(c.s, OP_MOVE, R_R10, R_R8); 647 x86_64_modrr(c.s, OP_MOVE, R_R8, R_R9); 648 x86_64_modrm(c.s, OP_LOAD, R_R9, R_RSP, 0, 0, 8); 649 x86_64_op(c.s, OP_SYSCALL); 650 x86_64_op(c.s, OP_RET); 651 } 652 653 d = find(c, "_restorer", nil, 1); 654 if (d.func_defined && !d.func_label.fixed) { 655 fixup_label(c.s, d.func_label); 656 add_symbol(c.s, d.name, d.func_label); 657 x86_64_modri(c.s, OP_MOVI, R_RAX, 15); 658 x86_64_op(c.s, OP_SYSCALL); 659 } 660 661 d = find(c, "_include", nil, 1); 662 if (d.func_defined && !d.func_label.fixed) { 663 fixup_label(c.s, d.func_label); 664 add_symbol(c.s, d.name, d.func_label); 665 x86_64_op(c.s, OP_UD2); 666 } 667 668 d = find(c, "ud2", nil, 1); 669 if (d.func_defined && !d.func_label.fixed) { 670 fixup_label(c.s, d.func_label); 671 add_symbol(c.s, d.name, d.func_label); 672 x86_64_op(c.s, OP_UD2); 673 } 674 675 d = find(c, "cpuid", nil, 1); 676 if (d.func_defined && !d.func_label.fixed) { 677 fixup_label(c.s, d.func_label); 678 add_symbol(c.s, d.name, d.func_label); 679 x86_64_opr(c.s, OP_PUSHR, R_RCX); 680 x86_64_opr(c.s, OP_PUSHR, R_RDX); 681 x86_64_opr(c.s, OP_PUSHR, R_RSI); 682 x86_64_opr(c.s, OP_PUSHR, R_RDI); 683 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RDI, 0, 0, 0); 684 x86_64_modrm(c.s, OP_LOAD, R_RCX, R_RSI, 0, 0, 0); 685 x86_64_modrm(c.s, OP_LOAD, R_RDX, R_RDX, 0, 0, 0); 686 x86_64_modrm(c.s, OP_LOAD, R_RBX, R_RCX, 0, 0, 0); 687 x86_64_op(c.s, OP_CPUID); 688 x86_64_opr(c.s, OP_POPR, R_RDI); 689 x86_64_opr(c.s, OP_POPR, R_RSI); 690 x86_64_opr(c.s, OP_POPR, R_RDX); 691 x86_64_opr(c.s, OP_POPR, R_RCX); 692 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 0); 693 x86_64_modrm(c.s, OP_STORE, R_RCX, R_RSI, 0, 0, 0); 694 x86_64_modrm(c.s, OP_STORE, R_RDX, R_RDX, 0, 0, 0); 695 x86_64_modrm(c.s, OP_STORE, R_RBX, R_RCX, 0, 0, 0); 696 x86_64_op(c.s, OP_RET); 697 } 698 699 d = find(c, "inb", nil, 1); 700 if (d.func_defined && !d.func_label.fixed) { 701 fixup_label(c.s, d.func_label); 702 add_symbol(c.s, d.name, d.func_label); 703 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RDI); 704 x86_64_op(c.s, OP_IN); 705 x86_64_op(c.s, OP_RET); 706 } 707 708 d = find(c, "outb", nil, 1); 709 if (d.func_defined && !d.func_label.fixed) { 710 fixup_label(c.s, d.func_label); 711 add_symbol(c.s, d.name, d.func_label); 712 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RDI); 713 x86_64_modrr(c.s, OP_MOVE, R_RAX, R_RSI); 714 x86_64_op(c.s, OP_OUT); 715 x86_64_op(c.s, OP_RET); 716 } 717 718 d = find(c, "inw", nil, 1); 719 if (d.func_defined && !d.func_label.fixed) { 720 fixup_label(c.s, d.func_label); 721 add_symbol(c.s, d.name, d.func_label); 722 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RDI); 723 as_emit(c.s, OP_OS); 724 x86_64_op(c.s, OP_IND); 725 x86_64_op(c.s, OP_RET); 726 } 727 728 d = find(c, "outw", nil, 1); 729 if (d.func_defined && !d.func_label.fixed) { 730 fixup_label(c.s, d.func_label); 731 add_symbol(c.s, d.name, d.func_label); 732 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RDI); 733 x86_64_modrr(c.s, OP_MOVE, R_RAX, R_RSI); 734 as_emit(c.s, OP_OS); 735 x86_64_op(c.s, OP_OUTD); 736 x86_64_op(c.s, OP_RET); 737 } 738 739 d = find(c, "ind", nil, 1); 740 if (d.func_defined && !d.func_label.fixed) { 741 fixup_label(c.s, d.func_label); 742 add_symbol(c.s, d.name, d.func_label); 743 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RDI); 744 x86_64_op(c.s, OP_IND); 745 x86_64_op(c.s, OP_RET); 746 } 747 748 d = find(c, "outd", nil, 1); 749 if (d.func_defined && !d.func_label.fixed) { 750 fixup_label(c.s, d.func_label); 751 add_symbol(c.s, d.name, d.func_label); 752 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RDI); 753 x86_64_modrr(c.s, OP_MOVE, R_RAX, R_RSI); 754 x86_64_op(c.s, OP_OUTD); 755 x86_64_op(c.s, OP_RET); 756 } 757 758 d = find(c, "rdmsr", nil, 1); 759 if (d.func_defined && !d.func_label.fixed) { 760 fixup_label(c.s, d.func_label); 761 add_symbol(c.s, d.name, d.func_label); 762 x86_64_modrr(c.s, OP_MOVE, R_RCX, R_RDI); 763 x86_64_op(c.s, OP_RDMSR); 764 x86_64_modri(c.s, OP_MOVI, R_RCX, 32); 765 x86_64_modr(c.s, OP_SHLM, R_RDX); 766 x86_64_modrr(c.s, OP_ORRM, R_RAX, R_RDX); 767 x86_64_op(c.s, OP_RET); 768 } 769 770 d = find(c, "wrmsr", nil, 1); 771 if (d.func_defined && !d.func_label.fixed) { 772 fixup_label(c.s, d.func_label); 773 add_symbol(c.s, d.name, d.func_label); 774 x86_64_modrr(c.s, OP_MOVE, R_RAX, R_RSI); 775 x86_64_modrr(c.s, OP_MOVE, R_RDX, R_RSI); 776 x86_64_modri(c.s, OP_MOVI, R_RCX, 32); 777 x86_64_modr(c.s, OP_SHRM, R_RDX); 778 x86_64_modrr(c.s, OP_MOVE, R_RCX, R_RDI); 779 x86_64_op(c.s, OP_WRMSR); 780 x86_64_op(c.s, OP_RET); 781 } 782 783 d = find(c, "rdcr0", nil, 1); 784 if (d.func_defined && !d.func_label.fixed) { 785 fixup_label(c.s, d.func_label); 786 add_symbol(c.s, d.name, d.func_label); 787 x86_64_modrr(c.s, OP_RDCRR, R_CR0, R_RAX); 788 x86_64_op(c.s, OP_RET); 789 } 790 791 d = find(c, "wrcr0", nil, 1); 792 if (d.func_defined && !d.func_label.fixed) { 793 fixup_label(c.s, d.func_label); 794 add_symbol(c.s, d.name, d.func_label); 795 x86_64_modrr(c.s, OP_WRCRR, R_CR0, R_RDI); 796 x86_64_op(c.s, OP_RET); 797 } 798 799 d = find(c, "rdcr2", nil, 1); 800 if (d.func_defined && !d.func_label.fixed) { 801 fixup_label(c.s, d.func_label); 802 add_symbol(c.s, d.name, d.func_label); 803 x86_64_modrr(c.s, OP_RDCRR, R_CR2, R_RAX); 804 x86_64_op(c.s, OP_RET); 805 } 806 807 d = find(c, "wrcr2", nil, 1); 808 if (d.func_defined && !d.func_label.fixed) { 809 fixup_label(c.s, d.func_label); 810 add_symbol(c.s, d.name, d.func_label); 811 x86_64_modrr(c.s, OP_WRCRR, R_CR2, R_RDI); 812 x86_64_op(c.s, OP_RET); 813 } 814 815 d = find(c, "rdcr3", nil, 1); 816 if (d.func_defined && !d.func_label.fixed) { 817 fixup_label(c.s, d.func_label); 818 add_symbol(c.s, d.name, d.func_label); 819 x86_64_modrr(c.s, OP_RDCRR, R_CR3, R_RAX); 820 x86_64_op(c.s, OP_RET); 821 } 822 823 d = find(c, "wrcr3", nil, 1); 824 if (d.func_defined && !d.func_label.fixed) { 825 fixup_label(c.s, d.func_label); 826 add_symbol(c.s, d.name, d.func_label); 827 x86_64_modrr(c.s, OP_WRCRR, R_CR3, R_RDI); 828 x86_64_op(c.s, OP_RET); 829 } 830 831 d = find(c, "rdcr4", nil, 1); 832 if (d.func_defined && !d.func_label.fixed) { 833 fixup_label(c.s, d.func_label); 834 add_symbol(c.s, d.name, d.func_label); 835 x86_64_modrr(c.s, OP_RDCRR, R_CR4, R_RAX); 836 x86_64_op(c.s, OP_RET); 837 } 838 839 d = find(c, "wrcr4", nil, 1); 840 if (d.func_defined && !d.func_label.fixed) { 841 fixup_label(c.s, d.func_label); 842 add_symbol(c.s, d.name, d.func_label); 843 x86_64_modrr(c.s, OP_WRCRR, R_CR4, R_RDI); 844 x86_64_op(c.s, OP_RET); 845 } 846 847 d = find(c, "lgdt", nil, 1); 848 if (d.func_defined && !d.func_label.fixed) { 849 fixup_label(c.s, d.func_label); 850 add_symbol(c.s, d.name, d.func_label); 851 x86_64_modri(c.s, OP_SUBI, R_RSP, 16); 852 x86_64_modri(c.s, OP_SUBI, R_RSI, 1); 853 x86_64_modrm(c.s, OP_STORE, R_RSI, R_RSP, 0, 0, 0); 854 x86_64_modrm(c.s, OP_STORE, R_RDI, R_RSP, 0, 0, 2); 855 x86_64_modm(c.s, OP_LGDTM, R_RSP, 0, 0, 0); 856 x86_64_modri(c.s, OP_ADDI, R_RSP, 16); 857 x86_64_op(c.s, OP_RET); 858 } 859 860 d = find(c, "lidt", nil, 1); 861 if (d.func_defined && !d.func_label.fixed) { 862 fixup_label(c.s, d.func_label); 863 add_symbol(c.s, d.name, d.func_label); 864 x86_64_modri(c.s, OP_SUBI, R_RSP, 16); 865 x86_64_modri(c.s, OP_SUBI, R_RSI, 1); 866 x86_64_modrm(c.s, OP_STORE, R_RSI, R_RSP, 0, 0, 0); 867 x86_64_modrm(c.s, OP_STORE, R_RDI, R_RSP, 0, 0, 2); 868 x86_64_modm(c.s, OP_LIDTM, R_RSP, 0, 0, 0); 869 x86_64_modri(c.s, OP_ADDI, R_RSP, 16); 870 x86_64_op(c.s, OP_RET); 871 } 872 873 d = find(c, "lldt", nil, 1); 874 if (d.func_defined && !d.func_label.fixed) { 875 fixup_label(c.s, d.func_label); 876 add_symbol(c.s, d.name, d.func_label); 877 x86_64_modr(c.s, OP_LLDTM, R_RDI); 878 x86_64_op(c.s, OP_RET); 879 } 880 881 d = find(c, "ltr", nil, 1); 882 if (d.func_defined && !d.func_label.fixed) { 883 fixup_label(c.s, d.func_label); 884 add_symbol(c.s, d.name, d.func_label); 885 x86_64_modr(c.s, OP_LTRM, R_RDI); 886 x86_64_op(c.s, OP_RET); 887 } 888 889 d = find(c, "lseg", nil, 1); 890 if (d.func_defined && !d.func_label.fixed) { 891 fixup_label(c.s, d.func_label); 892 add_symbol(c.s, d.name, d.func_label); 893 x86_64_opr(c.s, OP_PUSHR, R_RBP); 894 x86_64_modrr(c.s, OP_MOVE, R_RBP, R_RSP); 895 // es ds fs gs 896 x86_64_modrr(c.s, OP_WRSR, R_ES, R_RSI); 897 x86_64_modrr(c.s, OP_WRSR, R_DS, R_RSI); 898 x86_64_modrr(c.s, OP_WRSR, R_FS, R_RSI); 899 x86_64_modrr(c.s, OP_WRSR, R_GS, R_RSI); 900 // ss 901 x86_64_opr(c.s, OP_PUSHR, R_RSI); 902 // rsp 903 x86_64_opr(c.s, OP_PUSHR, R_RBP); 904 // flags 905 x86_64_op(c.s, OP_PUSHF); 906 // cs 907 x86_64_opr(c.s, OP_PUSHR, R_RDI); 908 // rip 909 x86_64_op(c.s, OP_CALL); 910 as_emit(c.s, 5); 911 as_emit(c.s, 0); 912 as_emit(c.s, 0); 913 as_emit(c.s, 0); 914 x86_64_op(c.s, OP_JMP); 915 as_emit(c.s, 2); 916 as_emit(c.s, 0); 917 as_emit(c.s, 0); 918 as_emit(c.s, 0); 919 x86_64_op(c.s, OP_IRETQ); 920 x86_64_opr(c.s, OP_POPR, R_RBP); 921 x86_64_op(c.s, OP_RET); 922 } 923 924 d = find(c, "hlt", nil, 1); 925 if (d.func_defined && !d.func_label.fixed) { 926 fixup_label(c.s, d.func_label); 927 add_symbol(c.s, d.name, d.func_label); 928 x86_64_op(c.s, OP_HLT); 929 x86_64_op(c.s, OP_RET); 930 } 931 932 d = find(c, "cli", nil, 1); 933 if (d.func_defined && !d.func_label.fixed) { 934 fixup_label(c.s, d.func_label); 935 add_symbol(c.s, d.name, d.func_label); 936 x86_64_op(c.s, OP_CLI); 937 x86_64_op(c.s, OP_RET); 938 } 939 940 d = find(c, "sti", nil, 1); 941 if (d.func_defined && !d.func_label.fixed) { 942 fixup_label(c.s, d.func_label); 943 add_symbol(c.s, d.name, d.func_label); 944 x86_64_op(c.s, OP_STI); 945 x86_64_op(c.s, OP_RET); 946 } 947 948 d = find(c, "rdflags", nil, 1); 949 if (d.func_defined && !d.func_label.fixed) { 950 fixup_label(c.s, d.func_label); 951 add_symbol(c.s, d.name, d.func_label); 952 x86_64_op(c.s, OP_PUSHF); 953 x86_64_opr(c.s, OP_POPR, R_RAX); 954 x86_64_op(c.s, OP_RET); 955 } 956 957 d = find(c, "wrflags", nil, 1); 958 if (d.func_defined && !d.func_label.fixed) { 959 fixup_label(c.s, d.func_label); 960 add_symbol(c.s, d.name, d.func_label); 961 x86_64_opr(c.s, OP_PUSHR, R_RDI); 962 x86_64_op(c.s, OP_POPF); 963 x86_64_op(c.s, OP_RET); 964 } 965 966 d = find(c, "wbinvld", nil, 1); 967 if (d.func_defined && !d.func_label.fixed) { 968 fixup_label(c.s, d.func_label); 969 add_symbol(c.s, d.name, d.func_label); 970 x86_64_modm(c.s, OP_WBINVD, R_RDI, 0, 0, 0); 971 x86_64_op(c.s, OP_RET); 972 } 973 974 d = find(c, "invlpg", nil, 1); 975 if (d.func_defined && !d.func_label.fixed) { 976 fixup_label(c.s, d.func_label); 977 add_symbol(c.s, d.name, d.func_label); 978 x86_64_modm(c.s, OP_INVLPGM, R_RDI, 0, 0, 0); 979 x86_64_op(c.s, OP_RET); 980 } 981 982 d = find(c, "_ssr0", nil, 1); 983 if (d.func_defined && !d.func_label.fixed) { 984 fixup_label(c.s, d.func_label); 985 add_symbol(c.s, d.name, d.func_label); 986 x86_64_ssr(c); 987 x86_64_op(c.s, OP_RET); 988 } 989 990 d = find(c, "_isr0", nil, 1); 991 if (d.func_defined && !d.func_label.fixed) { 992 fixup_label(c.s, d.func_label); 993 add_symbol(c.s, d.name, d.func_label); 994 x86_64_isr(c); 995 x86_64_op(c.s, OP_RET); 996 } 997 998 d = find(c, "_rgs", nil, 1); 999 if (d.func_defined && !d.func_label.fixed) { 1000 fixup_label(c.s, d.func_label); 1001 add_symbol(c.s, d.name, d.func_label); 1002 x86_64_modrm(c.s, OP_LOAD, R_RSI, R_RBP, 0, 0, 16); 1003 as_emit(c.s, OP_GS); 1004 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 0); 1005 x86_64_op(c.s, OP_RET); 1006 } 1007 1008 d = find(c, "_r32", nil, 1); 1009 if (d.func_defined && !d.func_label.fixed) { 1010 fixup_label(c.s, d.func_label); 1011 add_symbol(c.s, d.name, d.func_label); 1012 c.s.bits32 = 1; 1013 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RDI, 0, 0, 0); 1014 c.s.bits32 = 0; 1015 x86_64_op(c.s, OP_RET); 1016 } 1017 1018 d = find(c, "_w32", nil, 1); 1019 if (d.func_defined && !d.func_label.fixed) { 1020 fixup_label(c.s, d.func_label); 1021 add_symbol(c.s, d.name, d.func_label); 1022 c.s.bits32 = 1; 1023 x86_64_modrm(c.s, OP_STORE, R_RSI, R_RDI, 0, 0, 0); 1024 c.s.bits32 = 0; 1025 x86_64_op(c.s, OP_RET); 1026 } 1027 1028 d = find(c, "_r16", nil, 1); 1029 if (d.func_defined && !d.func_label.fixed) { 1030 fixup_label(c.s, d.func_label); 1031 add_symbol(c.s, d.name, d.func_label); 1032 x86_64_modrr(c.s, OP_XORRM, R_RAX, R_RAX); 1033 c.s.bits32 = 1; 1034 x86_64_modrm(c.s, OP_LOAD16, R_RAX, R_RDI, 0, 0, 0); 1035 c.s.bits32 = 0; 1036 x86_64_op(c.s, OP_RET); 1037 } 1038 1039 d = find(c, "_w16", nil, 1); 1040 if (d.func_defined && !d.func_label.fixed) { 1041 fixup_label(c.s, d.func_label); 1042 add_symbol(c.s, d.name, d.func_label); 1043 c.s.bits32 = 1; 1044 x86_64_modrm(c.s, OP_STORE16, R_RSI, R_RDI, 0, 0, 0); 1045 c.s.bits32 = 0; 1046 x86_64_op(c.s, OP_RET); 1047 } 1048 1049 d = find(c, "_rdrand", nil, 1); 1050 if (d.func_defined && !d.func_label.fixed) { 1051 fixup_label(c.s, d.func_label); 1052 add_symbol(c.s, d.name, d.func_label); 1053 x86_64_modr(c.s, OP_RDRAND, R_RAX); 1054 x86_64_op(c.s, OP_RET); 1055 } 1056 1057 d = find(c, "taskswitch", nil, 1); 1058 if (d.func_defined && !d.func_label.fixed) { 1059 fixup_label(c.s, d.func_label); 1060 add_symbol(c.s, d.name, d.func_label); 1061 1062 // save 1063 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 0); 1064 x86_64_modrm(c.s, OP_STORE, R_RCX, R_RDI, 0, 0, 8); 1065 x86_64_modrm(c.s, OP_STORE, R_RDX, R_RDI, 0, 0, 16); 1066 x86_64_modrm(c.s, OP_STORE, R_RBX, R_RDI, 0, 0, 24); 1067 x86_64_modrm(c.s, OP_STORE, R_RBP, R_RDI, 0, 0, 40); 1068 x86_64_modrm(c.s, OP_STORE, R_RSI, R_RDI, 0, 0, 48); 1069 x86_64_modrm(c.s, OP_STORE, R_RDI, R_RDI, 0, 0, 56); 1070 x86_64_modrm(c.s, OP_STORE, R_R8, R_RDI, 0, 0, 64); 1071 x86_64_modrm(c.s, OP_STORE, R_R9, R_RDI, 0, 0, 72); 1072 x86_64_modrm(c.s, OP_STORE, R_R10, R_RDI, 0, 0, 80); 1073 x86_64_modrm(c.s, OP_STORE, R_R11, R_RDI, 0, 0, 88); 1074 x86_64_modrm(c.s, OP_STORE, R_R12, R_RDI, 0, 0, 96); 1075 x86_64_modrm(c.s, OP_STORE, R_R13, R_RDI, 0, 0, 104); 1076 x86_64_modrm(c.s, OP_STORE, R_R14, R_RDI, 0, 0, 112); 1077 x86_64_modrm(c.s, OP_STORE, R_R15, R_RDI, 0, 0, 120); 1078 1079 // rip 1080 x86_64_opr(c.s, OP_POPR, R_RAX); 1081 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 128); 1082 // cs 1083 x86_64_modrr(c.s, OP_RDSR, R_CS, R_RAX); 1084 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 144); 1085 // flags 1086 x86_64_op(c.s, OP_PUSHF); 1087 x86_64_opr(c.s, OP_POPR, R_RAX); 1088 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 136); 1089 // rsp 1090 x86_64_modrm(c.s, OP_STORE, R_RSP, R_RDI, 0, 0, 32); 1091 // ss 1092 x86_64_modrr(c.s, OP_RDSR, R_SS, R_RAX); 1093 x86_64_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 152); 1094 1095 // restore 1096 x86_64_modrm(c.s, OP_STORE, R_RCX, R_RDI, 0, 0, 8); 1097 x86_64_modrm(c.s, OP_STORE, R_RDX, R_RDI, 0, 0, 16); 1098 x86_64_modrm(c.s, OP_STORE, R_RBX, R_RDI, 0, 0, 24); 1099 x86_64_modrm(c.s, OP_STORE, R_RBP, R_RDI, 0, 0, 40); 1100 x86_64_modrm(c.s, OP_STORE, R_RDI, R_RDI, 0, 0, 56); 1101 x86_64_modrm(c.s, OP_STORE, R_R8, R_RDI, 0, 0, 64); 1102 x86_64_modrm(c.s, OP_STORE, R_R9, R_RDI, 0, 0, 72); 1103 x86_64_modrm(c.s, OP_STORE, R_R10, R_RDI, 0, 0, 80); 1104 x86_64_modrm(c.s, OP_STORE, R_R11, R_RDI, 0, 0, 88); 1105 x86_64_modrm(c.s, OP_STORE, R_R12, R_RDI, 0, 0, 96); 1106 x86_64_modrm(c.s, OP_STORE, R_R13, R_RDI, 0, 0, 104); 1107 x86_64_modrm(c.s, OP_STORE, R_R14, R_RDI, 0, 0, 112); 1108 x86_64_modrm(c.s, OP_STORE, R_R15, R_RDI, 0, 0, 120); 1109 1110 // ss 1111 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 152); 1112 x86_64_opr(c.s, OP_PUSHR, R_RAX); 1113 // rsp 1114 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 32); 1115 x86_64_opr(c.s, OP_PUSHR, R_RAX); 1116 // flags 1117 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 136); 1118 x86_64_opr(c.s, OP_PUSHR, R_RAX); 1119 // cs 1120 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 144); 1121 x86_64_opr(c.s, OP_PUSHR, R_RAX); 1122 // rip 1123 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 128); 1124 x86_64_opr(c.s, OP_PUSHR, R_RAX); 1125 1126 // restore temporaries 1127 x86_64_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 0); 1128 x86_64_modrm(c.s, OP_LOAD, R_RSI, R_RSI, 0, 0, 40); 1129 1130 // iretq 1131 x86_64_op(c.s, OP_IRETQ); 1132 } 1133 } 1134 1135 func x86_64_kstart(c: *assembler) { 1136 var hang: *label; 1137 var do_iret: *label; 1138 var do_ret: *label; 1139 var done: *label; 1140 1141 c.bits32 = 1; 1142 1143 hang = mklabel(c); 1144 do_iret = mklabel(c); 1145 do_ret = mklabel(c); 1146 done = mklabel(c); 1147 1148 // Check for valid multiboot magic 1149 x86_64_modri(c, OP_MOVI, R_RDX, 0x2badb002); 1150 x86_64_modrr(c, OP_CMPRM, R_RAX, R_RDX); 1151 x86_64_jmp(c, OP_JCC + CC_NE, hang); 1152 1153 // Setup an initial stack 1154 x86_64_modri(c, OP_MOVI, R_RSP, 0x00300000); // FIXME bss 1155 1156 // Align stack to page 1157 x86_64_modri(c, OP_ANDI, R_RSP, -0x1000); 1158 1159 // pt3 -> 1g 1160 x86_64_modri(c, OP_SUBI, R_RSP, 0x1000); 1161 x86_64_modri(c, OP_MOVI, R_RAX, 0x83); 1162 x86_64_modri(c, OP_MOVI, R_RDX, 0); 1163 x86_64_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 0); 1164 x86_64_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 4); 1165 x86_64_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 510 * 8 + 0); 1166 x86_64_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 510 * 8 + 4); 1167 1168 // pt4 -> pt3 1169 x86_64_modrr(c, OP_MOVE, R_RAX, R_RSP); 1170 x86_64_modri(c, OP_SUBI, R_RSP, 0x1000); 1171 x86_64_modri(c, OP_ORI, R_RAX, 3); 1172 x86_64_modri(c, OP_MOVI, R_RDX, 0); 1173 x86_64_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 0); 1174 x86_64_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 4); 1175 x86_64_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 511 * 8 + 0); 1176 x86_64_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 511 * 8 + 4); 1177 1178 // Load page table pt4 1179 x86_64_modrr(c, OP_WRCRR, R_CR3, R_RSP); 1180 1181 // Allocate space for the gdt 1182 x86_64_modri(c, OP_SUBI, R_RSP, 64); 1183 x86_64_modrr(c, OP_MOVE, R_RBP, R_RSP); 1184 1185 // Null Segment 1186 x86_64_modri(c, OP_MOVI, R_RAX, 0x00000000); 1187 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 8); 1188 x86_64_modri(c, OP_MOVI, R_RAX, 0x00000000); 1189 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 12); 1190 1191 // Kernel code segment 1192 x86_64_modri(c, OP_MOVI, R_RAX, 0x00000000); 1193 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 16); 1194 x86_64_modri(c, OP_MOVI, R_RAX, 0x00209800); 1195 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 20); 1196 1197 // Kernel data segment 1198 x86_64_modri(c, OP_MOVI, R_RAX, 0x00000000); 1199 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 24); 1200 x86_64_modri(c, OP_MOVI, R_RAX, 0x00009200); 1201 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 28); 1202 1203 // Load gdt 1204 x86_64_modri(c, OP_MOVI, R_RAX, 23); 1205 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 0); 1206 x86_64_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, 8); 1207 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 2); 1208 x86_64_modm(c, OP_LGDTM, R_RBP, 0, 0, 0); 1209 1210 // Load null lldt 1211 x86_64_modri(c, OP_MOVI, R_RAX, 0); 1212 x86_64_modr(c, OP_LLDTM, R_RAX); 1213 1214 // Load null idt 1215 x86_64_modm(c, OP_LIDTM, R_RBP, 0, 0, 8); 1216 1217 // Enable pae 1218 x86_64_modri(c, OP_MOVI, R_RAX, 0xa0); 1219 x86_64_modrr(c, OP_WRCRR, R_CR4, R_RAX); 1220 1221 // Enable long mode 1222 x86_64_modri(c, OP_MOVI, R_RCX, (-1 << 32) + (0xc0 << 24) + 0x000080); 1223 x86_64_op(c, OP_RDMSR); 1224 x86_64_modri(c, OP_ORI, R_RAX, 0x100); 1225 x86_64_op(c, OP_WRMSR); 1226 1227 // Enable paging 1228 x86_64_modrr(c, OP_RDCRR, R_CR0, R_RAX); 1229 x86_64_modri(c, OP_ORI, R_RAX, (-0x80000000) | 0x0001); 1230 x86_64_modrr(c, OP_WRCRR, R_CR0, R_RAX); 1231 1232 // flags 1233 x86_64_modri(c, OP_MOVI, R_RAX, 0); 1234 x86_64_opr(c, OP_PUSHR, R_RAX); 1235 // cs 1236 x86_64_modri(c, OP_MOVI, R_RAX, 8); 1237 x86_64_opr(c, OP_PUSHR, R_RAX); 1238 // pointer 1239 x86_64_jmp(c, OP_CALL, do_iret); 1240 1241 c.bits32 = 0; 1242 1243 // Jump to top half 1244 x86_64_jmp(c, OP_CALL, do_ret); 1245 1246 // Reload the gdt in the top half 1247 x86_64_modri(c, OP_ORI, R_RBP, -0x80000000); 1248 x86_64_modri(c, OP_MOVI, R_RAX, 23); 1249 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 0); 1250 x86_64_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, 8); 1251 x86_64_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 2); 1252 x86_64_modm(c, OP_LGDTM, R_RBP, 0, 0, 0); 1253 1254 // Reload segments 1255 x86_64_modri(c, OP_MOVI, R_RAX, 16); 1256 x86_64_modrr(c, OP_WRSR, R_ES, R_RAX); 1257 x86_64_modrr(c, OP_WRSR, R_DS, R_RAX); 1258 x86_64_modrr(c, OP_WRSR, R_FS, R_RAX); 1259 x86_64_modrr(c, OP_WRSR, R_GS, R_RAX); 1260 x86_64_modrr(c, OP_WRSR, R_SS, R_RAX); 1261 x86_64_modrr(c, OP_MOVE, R_RSP, R_RSP); 1262 1263 // Reload stack in the top half 1264 x86_64_modri(c, OP_ORI, R_RSP, -0x80000000); 1265 1266 // Kill the lower mapping 1267 x86_64_modri(c, OP_MOVI, R_RAX, 0); 1268 x86_64_modrm(c, OP_LEA, R_RDI, R_RBP, 0, 0, 64); 1269 x86_64_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 4096); 1270 x86_64_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 0); 1271 x86_64_modri(c, OP_ANDI, R_RDI, 0x7fffffff); 1272 x86_64_modrr(c, OP_WRCRR, R_CR3, R_RDI); 1273 1274 // Setup a call frame for _kstart 1275 x86_64_jmp(c, OP_JMP, done); 1276 1277 // hlt forever 1278 fixup_label(c, hang); 1279 x86_64_op(c, OP_CLI); 1280 x86_64_op(c, OP_HLT); 1281 x86_64_jmp(c, OP_JMP, hang); 1282 1283 // iret to long mode 1284 fixup_label(c, do_iret); 1285 x86_64_op(c, OP_IRET); 1286 1287 // ret to top half 1288 fixup_label(c, do_ret); 1289 x86_64_opr(c, OP_POPR, R_RAX); 1290 x86_64_modri(c, OP_ORI, R_RAX, -0x80000000); 1291 x86_64_opr(c, OP_PUSHR, R_RAX); 1292 x86_64_op(c, OP_RET); 1293 1294 // Setup a call frame for _kstart 1295 fixup_label(c, done); 1296 x86_64_modrr(c, OP_XORRM, R_RBP, R_RBP); 1297 x86_64_modrr(c, OP_MOVE, R_RDI, R_RBX); 1298 x86_64_opr(c, OP_PUSHR, R_RBP); 1299 } 1300 1301 func x86_64_output_ir(c: *compiler, d: *decl) { 1302 var ic: *irfunc; 1303 1304 ic = d.func_ir; 1305 1306 ic.c.filename = ic.filename; 1307 ic.c.lineno = ic.lineno; 1308 ic.c.colno = ic.colno; 1309 ic.s.filename = ic.filename; 1310 ic.s.lineno = ic.lineno; 1311 1312 fixup_label(c.s, d.func_label); 1313 add_symbol(c.s, d.name, d.func_label); 1314 1315 if strcmp(d.name, "_start") == 0 { 1316 x86_64_modrm(c.s, OP_LOAD, R_RDI, R_RSP, 0, 0, 0); 1317 x86_64_modrm(c.s, OP_LEA, R_RSI, R_RSP, 0, 0, 8); 1318 x86_64_modrm(c.s, OP_LEA, R_RDX, R_RSI, R_RDI, 8, 8); 1319 x86_64_opr(c.s, OP_PUSHR, R_RBP); 1320 } else if strcmp(d.name, "_kstart") == 0 { 1321 x86_64_kstart(c.s); 1322 } 1323 1324 //fputc(nil, '\n'); 1325 //fputs(nil, d.name); 1326 //irshow(nil, ic.blocks[0]); 1327 1328 // Setup the frame 1329 x86_64_opr(ic.s, OP_PUSHR, R_RBP); 1330 x86_64_modrr(ic.s, OP_MOVE, R_RBP, R_RSP); 1331 1332 // Allocate local variables 1333 x86_64_output_irvars(ic); 1334 1335 // Output all blocks 1336 x86_64_output_irblock(ic, ic.blocks[0]); 1337 1338 // Clear the marks 1339 irreset(ic.blocks[0]); 1340 } 1341 1342 func x86_64_output_irvars(ic: *irfunc) { 1343 var offset: int; 1344 var size: int; 1345 var i: int; 1346 var v: *irvar; 1347 1348 // Allocate local variables 1349 offset = 0; 1350 i = 0; 1351 loop { 1352 if i == ic.vars_len { 1353 break; 1354 } 1355 1356 v = ic.vars[i]; 1357 1358 if v.dead { 1359 i = i + 1; 1360 continue; 1361 } 1362 1363 if v.t && v.t.kind != TY_VOID { 1364 size = type_sizeof(ic.c, v.t); 1365 } else { 1366 size = sizeof(i); 1367 } 1368 1369 size = (size + 7) & -8; 1370 1371 offset = offset + size; 1372 1373 v.offset = -offset; 1374 1375 i = i + 1; 1376 } 1377 1378 // Zero initialize local variables 1379 if offset != 0 { 1380 x86_64_modri(ic.s, OP_SUBI, R_RSP, offset); 1381 1382 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1383 1384 i = 0; 1385 loop { 1386 if i == offset { 1387 break; 1388 } 1389 1390 i = i + 8; 1391 1392 x86_64_modrm(ic.s, OP_STORE, R_RAX, R_RBP, 0, 0, -i); 1393 } 1394 } 1395 1396 // Save parameters 1397 i = 0; 1398 loop { 1399 if i == ic.arg_count { 1400 break; 1401 } 1402 1403 v = ic.vars[i]; 1404 1405 if i == 0 { 1406 x86_64_modrm(ic.s, OP_STORE, R_RDI, R_RBP, 0, 0, v.offset); 1407 } else if i == 1 { 1408 x86_64_modrm(ic.s, OP_STORE, R_RSI, R_RBP, 0, 0, v.offset); 1409 } else if i == 2 { 1410 x86_64_modrm(ic.s, OP_STORE, R_RDX, R_RBP, 0, 0, v.offset); 1411 } else if i == 3 { 1412 x86_64_modrm(ic.s, OP_STORE, R_RCX, R_RBP, 0, 0, v.offset); 1413 } else if i == 4 { 1414 x86_64_modrm(ic.s, OP_STORE, R_R8, R_RBP, 0, 0, v.offset); 1415 } else if i == 5 { 1416 x86_64_modrm(ic.s, OP_STORE, R_R9, R_RBP, 0, 0, v.offset); 1417 } else { 1418 // Stack argument 1419 x86_64_modrm(ic.s, OP_LOAD, R_RAX, R_RBP, 0, 0, (i - 6 + 2) * sizeof(i)); 1420 x86_64_modrm(ic.s, OP_STORE, R_RAX, R_RBP, 0, 0, v.offset); 1421 } 1422 1423 i = i + 1; 1424 } 1425 } 1426 1427 func x86_64_output_irblock(ic: *irfunc, b: *irblock) { 1428 var op: *irop; 1429 var i: int; 1430 1431 b.mark = 1; 1432 1433 if !b.done { 1434 cdie(ic.c, "no return in function"); 1435 } 1436 1437 fixup_label(ic.s, b.label); 1438 1439 i = 0; 1440 loop { 1441 if i == b.ops_len { 1442 break; 1443 } 1444 1445 op = b.ops[i]; 1446 1447 x86_64_output_irstmt(ic, b, op); 1448 1449 i = i + 1; 1450 } 1451 } 1452 1453 func x86_64_output_irstmt(ic: *irfunc, b: *irblock, o: *irop) { 1454 var kind: int; 1455 1456 ic.c.filename = o.filename; 1457 ic.c.lineno = o.lineno; 1458 ic.c.colno = o.colno; 1459 ic.s.filename = o.filename; 1460 ic.s.lineno = o.lineno; 1461 1462 kind = o.kind; 1463 if kind == IOP_STORE { 1464 // Evaluate the address 1465 if o.a.kind == IOP_LOAD { 1466 x86_64_output_irexpr(ic, b, o.a.a); 1467 } else if o.a.kind == IOP_VAR { 1468 x86_64_modrm(ic.s, OP_LEA, R_RAX, R_RBP, 0, 0, ic.vars[o.a.n].offset); 1469 } else { 1470 die("invalid store"); 1471 } 1472 1473 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1474 1475 // Evaluate the value 1476 x86_64_output_irexpr(ic, b, o.b); 1477 1478 x86_64_opr(ic.s, OP_POPR, R_RDI); 1479 1480 // Execute the store 1481 if o.t.kind == TY_BYTE { 1482 x86_64_modrm(ic.s, OP_STOREB, R_RAX, R_RDI, 0, 0, 0); 1483 } else if type_isprim(o.t) { 1484 x86_64_modrm(ic.s, OP_STORE, R_RAX, R_RDI, 0, 0, 0); 1485 } else { 1486 cdie(ic.c, "invalid store"); 1487 } 1488 } else if kind == IOP_RETVAL { 1489 // Do nothing 1490 } else if kind == IOP_ARG { 1491 // Do nothing 1492 } else if kind == IOP_CALL { 1493 // Allocate some space for the arguments 1494 if o.n > 6 { 1495 x86_64_modri(ic.s, OP_SUBI, R_RSP, (o.n - 6) * sizeof(kind)); 1496 } 1497 1498 // Setup arguments 1499 x86_64_output_irargs(ic, b, o); 1500 1501 // Call the function 1502 if o.a.kind == IOP_FUNC { 1503 x86_64_output_ircall(ic, b, o.a); 1504 } else { 1505 x86_64_output_irexpr(ic, b, o.a); 1506 x86_64_modr(ic.s, OP_ICALLM, R_RAX); 1507 } 1508 1509 // Release space reserved for the arguments 1510 if o.n > 6 { 1511 x86_64_modri(ic.s, OP_ADDI, R_RSP, (o.n - 6) * sizeof(kind)); 1512 } 1513 1514 // Save the return value 1515 x86_64_output_irretval(ic, b, o); 1516 1517 if b.out.mark { 1518 x86_64_jmp(ic.s, OP_JMP, b.out.label); 1519 } else { 1520 x86_64_output_irblock(ic, b.out); 1521 } 1522 return; 1523 } else if kind == IOP_JUMP { 1524 if b.out.mark { 1525 // Jump to an already output block 1526 x86_64_jmp(ic.s, OP_JMP, b.out.label); 1527 } else { 1528 // Output a new block 1529 x86_64_output_irblock(ic, b.out); 1530 } 1531 return; 1532 } else if kind == IOP_BRANCH { 1533 // Evaluate the condition and branch if zero 1534 x86_64_output_irexpr(ic, b, o.a); 1535 x86_64_modrr(ic.s, OP_TESTRM, R_RAX, R_RAX); 1536 x86_64_jmp(ic.s, OP_JCC + CC_E, b.alt.label); 1537 1538 // Then jump to the output 1539 if b.out.mark { 1540 x86_64_jmp(ic.s, OP_JCC + CC_NE, b.out.label); 1541 } else { 1542 x86_64_output_irblock(ic, b.out); 1543 } 1544 1545 // And if we haven't already, output the alt branch 1546 if !b.alt.mark { 1547 x86_64_output_irblock(ic, b.alt); 1548 } 1549 1550 return; 1551 } else if kind == IOP_RETURN { 1552 // Evaluate the return expression and return 1553 if o.a { 1554 x86_64_output_irexpr(ic, b, o.a); 1555 } 1556 1557 x86_64_modrr(ic.s, OP_MOVE, R_RSP, R_RBP); 1558 x86_64_opr(ic.s, OP_POPR, R_RBP); 1559 x86_64_op(ic.s, OP_RET); 1560 } else { 1561 // Evaluate and discard the result 1562 x86_64_output_irexpr(ic, b, o); 1563 } 1564 } 1565 1566 func x86_64_output_irargs(ic: *irfunc, b: *irblock, o: *irop) { 1567 var i: int; 1568 var op: *irop; 1569 1570 i = 0; 1571 loop { 1572 if i == b.ops_len { 1573 return; 1574 } 1575 1576 op = b.ops[i]; 1577 if op.kind == IOP_ARG { 1578 // Compute the value 1579 x86_64_output_irexpr(ic, b, op.a); 1580 1581 if op.n == 0 { 1582 x86_64_modrr(ic.s, OP_MOVE, R_RDI, R_RAX); 1583 } else if op.n == 1 { 1584 x86_64_modrr(ic.s, OP_MOVE, R_RSI, R_RAX); 1585 } else if op.n == 2 { 1586 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1587 } else if op.n == 3 { 1588 x86_64_modrr(ic.s, OP_MOVE, R_RCX, R_RAX); 1589 } else if op.n == 4 { 1590 x86_64_modrr(ic.s, OP_MOVE, R_R8, R_RAX); 1591 } else if op.n == 5 { 1592 x86_64_modrr(ic.s, OP_MOVE, R_R9, R_RAX); 1593 } else { 1594 // Stack argument 1595 x86_64_modrm(ic.s, OP_STORE, R_RAX, R_RSP, 0, 0, (op.n - 6) * sizeof(i)); 1596 } 1597 } 1598 1599 i = i + 1; 1600 } 1601 } 1602 1603 func x86_64_output_irretval(ic: *irfunc, b: *irblock, o: *irop) { 1604 var i: int; 1605 var op: *irop; 1606 1607 // Find the retval place 1608 op = nil; 1609 i = 0; 1610 loop { 1611 if i == b.ops_len { 1612 return; 1613 } 1614 1615 op = b.ops[i]; 1616 if op.kind == IOP_RETVAL { 1617 break; 1618 } 1619 1620 i = i + 1; 1621 } 1622 1623 // Do nothing if there was no return value 1624 if op.t.kind == TY_VOID { 1625 return; 1626 } 1627 1628 // Save the value 1629 x86_64_modrr(ic.s, OP_MOVE, R_RDI, R_RAX); 1630 1631 // Compute the address 1632 if op.a.kind == IOP_LOAD { 1633 x86_64_output_irexpr(ic, b, op.a.a); 1634 } else if op.a.kind == IOP_VAR { 1635 x86_64_modrm(ic.s, OP_LEA, R_RAX, R_RBP, 0, 0, ic.vars[op.a.n].offset); 1636 } else { 1637 die("invalid store"); 1638 } 1639 1640 // Execute the store 1641 if op.t.kind == TY_BYTE { 1642 x86_64_modrm(ic.s, OP_STOREB, R_RDI, R_RAX, 0, 0, 0); 1643 } else if type_isprim(op.t) { 1644 x86_64_modrm(ic.s, OP_STORE, R_RDI, R_RAX, 0, 0, 0); 1645 } else { 1646 cdie(ic.c, "invalid store"); 1647 } 1648 } 1649 1650 func x86_64_output_irstr(ic: *irfunc, b: *irblock, o: *irop) { 1651 var s: *label; 1652 1653 s = as_blob(ic.s, o.s, o.slen + 1); 1654 1655 reserve(ic.s, 16); 1656 x86_64_modrm(ic.s, OP_LEA, R_RAX, R_RIP, 0, 0, 128); 1657 addfixup(ic.s, s, FIXUP_DISP32); 1658 } 1659 1660 func x86_64_output_irfuncptr(ic: *irfunc, b: *irblock, o: *irop) { 1661 var d: *decl; 1662 1663 d = find(ic.c, o.s, nil, 0); 1664 1665 if !d || !d.func_defined { 1666 cdie(ic.c, "no such function"); 1667 } 1668 1669 reserve(ic.s, 16); 1670 x86_64_modrm(ic.s, OP_LEA, R_RAX, R_RIP, 0, 0, 128); 1671 addfixup(ic.s, d.func_label, FIXUP_DISP32); 1672 } 1673 1674 func x86_64_output_ircall(ic: *irfunc, b: *irblock, o: *irop) { 1675 var d: *decl; 1676 1677 d = find(ic.c, o.s, nil, 0); 1678 1679 if !d || !d.func_defined { 1680 cdie(ic.c, "no such function"); 1681 } 1682 1683 x86_64_jmp(ic.s, OP_CALL, d.func_label); 1684 } 1685 1686 func x86_64_output_irexpr(ic: *irfunc, b: *irblock, o: *irop) { 1687 var kind: int; 1688 1689 if !o { 1690 cdie(ic.c, "no expr"); 1691 } 1692 1693 kind = o.kind; 1694 if kind == IOP_VAR { 1695 x86_64_modrm(ic.s, OP_LOAD, R_RAX, R_RBP, 0, 0, ic.vars[o.n].offset); 1696 } else if kind == IOP_VARREF { 1697 x86_64_modrm(ic.s, OP_LEA, R_RAX, R_RBP, 0, 0, ic.vars[o.n].offset); 1698 } else if kind == IOP_FUNC { 1699 x86_64_output_irfuncptr(ic, b, o); 1700 } else if kind == IOP_CONST { 1701 if o.n == 0 { 1702 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1703 } else if o.n < (-1 >> 33) && o.n >= (-1 << 31) { 1704 x86_64_modri(ic.s, OP_MOVI, R_RAX, o.n); 1705 } else { 1706 x86_64_opri64(ic.s, OP_MOVABS, R_RAX, o.n); 1707 } 1708 } else if kind == IOP_STR { 1709 x86_64_output_irstr(ic, b, o); 1710 } else if kind == IOP_LOAD { 1711 x86_64_output_irexpr(ic, b, o.a); 1712 if o.t.kind == TY_BYTE { 1713 x86_64_modrr(ic.s, OP_MOVE, R_RSI, R_RAX); 1714 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1715 x86_64_modrm(ic.s, OP_LOADB, R_RAX, R_RSI, 0, 0, 0); 1716 } else if type_isprim(o.t) { 1717 x86_64_modrm(ic.s, OP_LOAD, R_RAX, R_RAX, 0, 0, 0); 1718 } else { 1719 cdie(ic.c, "invalid load"); 1720 } 1721 } else if kind == IOP_NEG { 1722 x86_64_output_irexpr(ic, b, o.a); 1723 x86_64_modr(ic.s, OP_NEGM, R_RAX); 1724 } else if kind == IOP_NOT { 1725 x86_64_output_irexpr(ic, b, o.a); 1726 x86_64_modr(ic.s, OP_NOTM, R_RAX); 1727 } else if kind == IOP_ADD { 1728 x86_64_output_irexpr(ic, b, o.b); 1729 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1730 x86_64_output_irexpr(ic, b, o.a); 1731 x86_64_opr(ic.s, OP_POPR, R_RCX); 1732 x86_64_modrr(ic.s, OP_ADDRM, R_RAX, R_RCX); 1733 } else if kind == IOP_AND { 1734 x86_64_output_irexpr(ic, b, o.b); 1735 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1736 x86_64_output_irexpr(ic, b, o.a); 1737 x86_64_opr(ic.s, OP_POPR, R_RCX); 1738 x86_64_modrr(ic.s, OP_ANDRM, R_RAX, R_RCX); 1739 } else if kind == IOP_OR { 1740 x86_64_output_irexpr(ic, b, o.b); 1741 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1742 x86_64_output_irexpr(ic, b, o.a); 1743 x86_64_opr(ic.s, OP_POPR, R_RCX); 1744 x86_64_modrr(ic.s, OP_ORRM, R_RAX, R_RCX); 1745 } else if kind == IOP_XOR { 1746 x86_64_output_irexpr(ic, b, o.b); 1747 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1748 x86_64_output_irexpr(ic, b, o.a); 1749 x86_64_opr(ic.s, OP_POPR, R_RCX); 1750 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RCX); 1751 } else if kind == IOP_DIV { 1752 x86_64_output_irexpr(ic, b, o.b); 1753 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1754 x86_64_output_irexpr(ic, b, o.a); 1755 x86_64_opr(ic.s, OP_POPR, R_RCX); 1756 x86_64_modrr(ic.s, OP_XORRM, R_RDX, R_RDX); 1757 x86_64_modrr(ic.s, OP_TESTRM, R_RAX, R_RAX); 1758 x86_64_modrr(ic.s, OP_SETCC + CC_S, 0, R_RDX); 1759 x86_64_modr(ic.s, OP_NEGM, R_RDX); 1760 x86_64_modr(ic.s, OP_IDIVM, R_RCX); 1761 } else if kind == IOP_MOD { 1762 x86_64_output_irexpr(ic, b, o.b); 1763 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1764 x86_64_output_irexpr(ic, b, o.a); 1765 x86_64_opr(ic.s, OP_POPR, R_RCX); 1766 x86_64_modrr(ic.s, OP_XORRM, R_RDX, R_RDX); 1767 x86_64_modrr(ic.s, OP_TESTRM, R_RAX, R_RAX); 1768 x86_64_modrr(ic.s, OP_SETCC + CC_S, 0, R_RDX); 1769 x86_64_modr(ic.s, OP_NEGM, R_RDX); 1770 x86_64_modr(ic.s, OP_IDIVM, R_RCX); 1771 x86_64_modrr(ic.s, OP_MOVE, R_RAX, R_RDX); 1772 } else if kind == IOP_LSH { 1773 x86_64_output_irexpr(ic, b, o.b); 1774 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1775 x86_64_output_irexpr(ic, b, o.a); 1776 x86_64_opr(ic.s, OP_POPR, R_RCX); 1777 x86_64_modr(ic.s, OP_SHLM, R_RAX); 1778 } else if kind == IOP_RSH { 1779 x86_64_output_irexpr(ic, b, o.b); 1780 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1781 x86_64_output_irexpr(ic, b, o.a); 1782 x86_64_opr(ic.s, OP_POPR, R_RCX); 1783 x86_64_modr(ic.s, OP_SHRM, R_RAX); 1784 } else if kind == IOP_MUL { 1785 x86_64_output_irexpr(ic, b, o.b); 1786 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1787 x86_64_output_irexpr(ic, b, o.a); 1788 x86_64_opr(ic.s, OP_POPR, R_RCX); 1789 x86_64_modr(ic.s, OP_IMULM, R_RCX); 1790 } else if kind == IOP_SUB { 1791 x86_64_output_irexpr(ic, b, o.b); 1792 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1793 x86_64_output_irexpr(ic, b, o.a); 1794 x86_64_opr(ic.s, OP_POPR, R_RCX); 1795 x86_64_modrr(ic.s, OP_SUBRM, R_RAX, R_RCX); 1796 } else if kind == IOP_EQ { 1797 x86_64_output_irexpr(ic, b, o.b); 1798 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1799 x86_64_output_irexpr(ic, b, o.a); 1800 x86_64_opr(ic.s, OP_POPR, R_RCX); 1801 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1802 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1803 x86_64_modrr(ic.s, OP_CMPRM, R_RDX, R_RCX); 1804 x86_64_modrr(ic.s, OP_SETCC + CC_E, 0, R_RAX); 1805 } else if kind == IOP_NE { 1806 x86_64_output_irexpr(ic, b, o.b); 1807 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1808 x86_64_output_irexpr(ic, b, o.a); 1809 x86_64_opr(ic.s, OP_POPR, R_RCX); 1810 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1811 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1812 x86_64_modrr(ic.s, OP_CMPRM, R_RDX, R_RCX); 1813 x86_64_modrr(ic.s, OP_SETCC + CC_NE, 0, R_RAX); 1814 } else if kind == IOP_GT { 1815 x86_64_output_irexpr(ic, b, o.b); 1816 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1817 x86_64_output_irexpr(ic, b, o.a); 1818 x86_64_opr(ic.s, OP_POPR, R_RCX); 1819 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1820 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1821 x86_64_modrr(ic.s, OP_CMPRM, R_RDX, R_RCX); 1822 x86_64_modrr(ic.s, OP_SETCC + CC_G, 0, R_RAX); 1823 } else if kind == IOP_GE { 1824 x86_64_output_irexpr(ic, b, o.b); 1825 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1826 x86_64_output_irexpr(ic, b, o.a); 1827 x86_64_opr(ic.s, OP_POPR, R_RCX); 1828 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1829 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1830 x86_64_modrr(ic.s, OP_CMPRM, R_RDX, R_RCX); 1831 x86_64_modrr(ic.s, OP_SETCC + CC_GE, 0, R_RAX); 1832 } else if kind == IOP_LT { 1833 x86_64_output_irexpr(ic, b, o.b); 1834 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1835 x86_64_output_irexpr(ic, b, o.a); 1836 x86_64_opr(ic.s, OP_POPR, R_RCX); 1837 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1838 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1839 x86_64_modrr(ic.s, OP_CMPRM, R_RDX, R_RCX); 1840 x86_64_modrr(ic.s, OP_SETCC + CC_L, 0, R_RAX); 1841 } else if kind == IOP_LE { 1842 x86_64_output_irexpr(ic, b, o.b); 1843 x86_64_opr(ic.s, OP_PUSHR, R_RAX); 1844 x86_64_output_irexpr(ic, b, o.a); 1845 x86_64_opr(ic.s, OP_POPR, R_RCX); 1846 x86_64_modrr(ic.s, OP_MOVE, R_RDX, R_RAX); 1847 x86_64_modrr(ic.s, OP_XORRM, R_RAX, R_RAX); 1848 x86_64_modrr(ic.s, OP_CMPRM, R_RDX, R_RCX); 1849 x86_64_modrr(ic.s, OP_SETCC + CC_LE, 0, R_RAX); 1850 } else { 1851 cdie(ic.c, "invalid op"); 1852 } 1853 }