- /*
- ** This file has been pre-processed with DynASM.
- ** http://luajit.org/dynasm.html
- ** DynASM version 1.3.0, DynASM x64 version 1.3.0
- ** DO NOT EDIT! The original file is in "vm_x86.dasc".
- */
- #line 1 "vm_x86.dasc"
- //|// Low-level VM code for x86 CPUs.
- //|// Bytecode interpreter, fast functions and helper functions.
- //|// Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
- //|
- //|.if P64
- //|.arch x64
- #if DASM_VERSION != 10300
- #error "Version mismatch between DynASM and included encoding engine"
- #endif
- #line 7 "vm_x86.dasc"
- //|.else
- //|.arch x86
- //|.endif
- //|.section code_op, code_sub
- #define DASM_SECTION_CODE_OP 0
- #define DASM_SECTION_CODE_SUB 1
- #define DASM_MAXSECTION 2
- #line 11 "vm_x86.dasc"
- //|
- //|.actionlist build_actionlist
- static const unsigned char build_actionlist[14864] = {
- 254,1,248,10,252,247,195,237,15,132,244,11,131,227,252,248,41,218,72,141,
- 76,25,252,248,139,90,252,252,199,68,10,4,237,248,12,131,192,1,15,132,244,
- 13,137,68,36,4,252,247,195,237,15,132,244,14,248,15,129,252,243,239,252,247,
- 195,237,15,133,244,10,65,199,134,233,237,131,227,252,248,41,211,252,247,219,
- 131,232,1,15,132,244,248,248,1,255,72,139,44,10,72,137,106,252,248,131,194,
- 8,131,232,1,15,133,244,1,248,2,139,108,36,24,137,157,233,248,3,139,68,36,
- 4,139,76,36,16,248,4,57,193,15,133,244,252,248,5,131,252,234,8,137,149,233,
- 248,16,72,139,76,36,32,72,137,141,233,49,192,248,17,72,131,196,40,65,94,65,
- 95,91,93,195,248,6,15,130,244,253,59,149,233,15,135,244,254,199,66,252,252,
- 237,255,131,194,8,131,192,1,252,233,244,4,248,7,133,201,15,132,244,5,41,193,
- 141,20,202,252,233,244,5,248,8,137,149,233,137,68,36,4,137,206,137,252,239,
- 232,251,1,0,139,149,233,252,233,244,3,248,13,176,235,252,233,244,18,248,19,
- 137,252,240,72,137,252,252,248,18,139,108,36,24,139,173,233,199,133,233,237,
- 255,252,233,244,17,248,20,139,124,36,24,137,198,72,131,196,40,65,94,65,95,
- 91,93,252,233,251,1,1,248,21,72,129,231,239,72,137,252,252,248,22,139,108,
- 36,24,72,199,193,252,248,252,255,252,255,252,255,184,237,139,149,233,68,139,
- 181,233,65,129,198,239,139,90,252,252,199,66,252,252,237,65,199,134,233,237,
- 252,233,244,12,248,23,190,237,252,233,244,248,248,24,255,131,232,8,252,233,
- 244,247,248,25,141,68,194,252,248,248,1,15,182,139,233,131,195,4,137,149,
- 233,137,133,233,137,92,36,28,137,206,248,2,137,252,239,232,251,1,0,139,149,
- 233,139,133,233,139,106,252,248,41,208,193,232,3,131,192,1,139,157,233,139,
- 11,15,182,252,233,15,182,205,131,195,4,65,252,255,36,252,238,248,26,85,83,
- 65,87,65,86,72,131,252,236,40,137,252,253,137,124,36,24,137,252,241,187,237,
- 49,192,76,141,188,253,36,233,68,139,181,233,65,129,198,239,137,68,36,28,72,
- 137,68,36,32,137,68,36,16,137,68,36,20,76,137,189,233,56,133,233,15,132,244,
- 248,255,65,137,174,233,65,199,134,233,237,136,133,233,139,149,233,139,133,
- 233,41,200,193,232,3,131,192,1,41,209,139,90,252,252,137,68,36,4,252,247,
- 195,237,15,132,244,14,252,233,244,15,248,27,85,83,65,87,65,86,72,131,252,
- 236,40,187,237,137,76,36,20,252,233,244,247,248,28,85,83,65,87,65,86,72,131,
- 252,236,40,187,237,248,1,137,84,36,16,137,252,253,137,124,36,24,137,252,241,
- 68,139,181,233,76,139,189,233,255,76,137,124,36,32,137,108,36,28,65,129,198,
- 239,72,137,165,233,248,2,65,137,174,233,65,199,134,233,237,139,149,233,1,
- 203,41,211,139,133,233,41,200,193,232,3,131,192,1,248,29,139,105,252,248,
- 129,121,253,252,252,239,15,133,244,30,248,31,137,202,137,90,252,252,139,157,
- 233,139,11,15,182,252,233,15,182,205,131,195,4,65,252,255,36,252,238,248,
- 32,85,83,65,87,65,86,72,131,252,236,40,137,252,253,137,124,36,24,137,108,
- 36,28,68,139,189,233,68,43,189,233,68,139,181,233,199,68,36,20,0,0,0,0,68,
- 137,124,36,16,65,129,198,239,76,139,189,233,255,76,137,124,36,32,72,137,165,
- 233,65,137,174,233,252,255,209,133,192,15,132,244,16,137,193,187,237,252,
- 233,244,2,248,11,1,209,131,227,252,248,137,213,41,218,199,68,193,252,252,
- 237,137,200,139,93,252,244,72,99,77,252,240,131,252,249,1,15,134,244,247,
- 76,141,61,245,76,1,252,249,68,139,122,252,248,69,139,191,233,69,139,191,233,
- 252,255,225,248,1,15,132,244,33,41,213,193,252,237,3,141,69,252,255,252,233,
- 244,34,248,35,255,15,182,75,252,255,131,252,237,16,141,12,202,41,252,233,
- 15,132,244,36,252,247,217,193,252,233,3,139,124,36,24,137,151,233,137,202,
- 72,139,8,72,137,77,0,137,252,238,252,233,244,37,248,38,137,4,36,199,68,36,
- 4,237,72,141,4,36,128,123,252,252,235,15,133,244,247,65,141,142,233,137,41,
- 199,65,4,237,137,205,252,233,244,248,248,39,15,182,67,252,254,199,68,36,4,
- 237,137,4,36,72,141,4,36,252,233,244,247,248,40,15,182,67,252,254,141,4,194,
- 248,1,255,15,182,107,252,255,141,44,252,234,248,2,139,124,36,24,137,151,233,
- 137,252,238,72,137,194,137,252,253,137,92,36,28,232,251,1,2,139,149,233,133,
- 192,15,132,244,249,248,36,15,182,75,252,253,72,139,40,72,137,44,202,139,3,
- 15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,3,139,
- 141,233,137,89,252,244,141,153,233,41,211,139,105,252,248,184,237,252,233,
- 244,31,248,41,137,252,239,137,213,137,198,232,251,1,3,15,182,75,252,253,137,
- 252,234,133,192,15,133,244,42,199,68,202,4,237,252,233,244,43,248,44,137,
- 4,36,199,68,36,4,237,255,72,141,4,36,128,123,252,252,235,15,133,244,247,65,
- 141,142,233,137,41,199,65,4,237,137,205,252,233,244,248,248,45,15,182,67,
- 252,254,199,68,36,4,237,137,4,36,72,141,4,36,252,233,244,247,248,46,15,182,
- 67,252,254,141,4,194,248,1,15,182,107,252,255,141,44,252,234,248,2,139,124,
- 36,24,137,151,233,137,252,238,72,137,194,137,252,253,137,92,36,28,232,251,
- 1,4,139,149,233,133,192,15,132,244,249,15,182,75,252,253,72,139,44,202,72,
- 137,40,248,47,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,
- 36,252,238,248,3,255,139,141,233,137,89,252,244,15,182,67,252,253,72,139,
- 44,194,72,137,105,16,141,153,233,41,211,139,105,252,248,184,237,252,233,244,
- 31,248,48,139,124,36,24,137,252,238,137,151,233,137,213,137,194,137,92,36,
- 28,232,251,1,5,15,182,75,252,253,137,252,234,252,233,244,49,248,50,139,108,
- 36,24,137,149,233,141,52,202,141,20,194,137,252,239,15,182,75,252,252,137,
- 92,36,28,232,251,1,6,248,3,139,149,233,131,252,248,1,15,135,244,51,248,4,
- 141,91,4,15,130,244,252,248,5,15,183,67,252,254,141,156,253,131,233,248,6,
- 255,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,
- 248,52,131,195,4,129,120,253,4,239,15,130,244,5,252,233,244,6,248,53,129,
- 120,253,4,239,252,233,244,4,248,54,131,252,235,4,137,206,137,252,233,139,
- 108,36,24,137,149,233,137,194,137,252,239,137,92,36,28,232,251,1,7,252,233,
- 244,3,248,55,131,252,235,4,139,108,36,24,137,149,233,137,252,239,139,115,
- 252,252,137,92,36,28,232,251,1,8,252,233,244,3,248,56,139,108,36,24,137,149,
- 233,255,137,206,15,183,83,252,254,137,252,239,137,92,36,28,232,251,1,9,139,
- 149,233,252,233,244,6,248,57,15,182,107,252,255,248,58,65,141,4,199,252,233,
- 244,247,248,59,15,182,67,252,254,248,60,65,141,4,199,141,44,252,234,149,252,
- 233,244,248,248,61,141,4,194,137,197,252,233,244,248,248,62,15,182,107,252,
- 255,248,63,141,4,194,248,1,141,44,252,234,248,2,141,12,202,68,15,182,67,252,
- 252,137,206,137,193,139,124,36,24,137,151,233,137,252,234,137,252,253,137,
- 92,36,28,232,251,1,10,139,149,233,255,133,192,15,132,244,47,248,51,137,193,
- 41,208,137,89,252,244,141,152,233,184,237,252,233,244,29,248,64,139,108,36,
- 24,137,149,233,141,52,194,137,252,239,137,92,36,28,232,251,1,11,139,149,233,
- 255,133,192,15,133,244,51,15,183,67,252,254,139,60,194,252,233,244,65,255,
- 252,233,244,51,255,248,66,141,76,202,8,248,30,137,76,36,4,137,4,36,131,252,
- 233,8,139,108,36,24,137,149,233,137,206,141,20,193,137,252,239,137,92,36,
- 28,232,251,1,12,139,149,233,139,76,36,4,139,4,36,139,105,252,248,131,192,
- 1,65,57,215,15,132,244,67,137,202,137,90,252,252,139,157,233,139,11,15,182,
- 252,233,15,182,205,131,195,4,65,252,255,36,252,238,248,68,139,108,36,24,137,
- 149,233,137,206,137,252,239,137,92,36,28,232,251,1,13,139,149,233,139,67,
- 252,252,15,182,204,15,182,232,193,232,16,65,252,255,164,253,252,238,233,248,
- 69,129,252,248,239,15,130,244,70,139,106,4,129,252,253,239,15,131,244,70,
- 139,90,252,252,137,68,36,4,137,106,252,252,139,42,137,106,252,248,131,232,
- 2,15,132,244,248,255,137,209,248,1,131,193,8,72,139,41,72,137,105,252,248,
- 131,232,1,15,133,244,1,248,2,139,68,36,4,252,233,244,71,248,72,129,252,248,
- 239,15,130,244,70,139,106,4,137,252,233,193,252,249,15,131,252,249,252,254,
- 15,132,244,249,184,237,252,247,213,57,232,15,71,197,248,2,139,106,252,248,
- 139,132,253,197,233,139,90,252,252,199,66,252,252,237,137,66,252,248,252,
- 233,244,73,248,3,184,237,255,252,233,244,2,248,74,129,252,248,239,15,130,
- 244,70,139,106,4,139,90,252,252,129,252,253,239,15,133,244,252,248,1,139,
- 42,139,173,233,248,2,133,252,237,199,66,252,252,237,15,132,244,73,65,139,
- 134,233,199,66,252,252,237,137,106,252,248,139,141,233,35,136,233,105,201,
- 239,255,3,141,233,248,3,129,185,233,239,15,133,244,250,57,129,233,15,132,
- 244,251,248,4,139,137,233,133,201,15,133,244,3,252,233,244,73,248,5,139,105,
- 4,129,252,253,239,15,132,244,73,139,1,137,106,252,252,137,66,252,248,252,
- 233,244,73,248,6,255,129,252,253,239,15,132,244,1,129,252,253,239,15,135,
- 244,254,129,252,253,239,15,134,244,253,189,237,252,233,244,254,248,7,189,
- 237,248,8,252,247,213,65,139,172,253,174,233,252,233,244,2,248,75,129,252,
- 248,239,255,15,130,244,70,129,122,253,4,239,15,133,244,70,139,42,131,189,
- 233,0,15,133,244,70,129,122,253,12,239,15,133,244,70,139,66,8,137,133,233,
- 139,90,252,252,199,66,252,252,237,137,106,252,248,252,246,133,233,235,15,
- 132,244,247,128,165,233,235,65,139,134,233,255,65,137,174,233,137,133,233,
- 248,1,252,233,244,73,248,76,129,252,248,239,15,130,244,70,129,122,253,4,239,
- 15,133,244,70,137,213,139,50,141,82,8,139,124,36,24,232,251,1,14,137,252,
- 234,72,139,40,139,90,252,252,72,137,106,252,248,252,233,244,73,248,77,129,
- 252,248,239,15,133,244,70,129,122,253,4,239,15,133,244,247,255,139,42,252,
- 233,244,78,248,1,15,135,244,70,252,242,15,16,2,252,233,244,79,248,80,129,
- 252,248,239,15,130,244,70,139,90,252,252,129,122,253,4,239,15,133,244,249,
- 139,2,248,2,199,66,252,252,237,137,66,252,248,252,233,244,73,248,3,129,122,
- 253,4,239,255,15,135,244,70,65,131,190,233,0,15,133,244,70,65,139,174,233,
- 65,59,174,233,15,130,244,247,232,244,81,248,1,139,108,36,24,137,149,233,137,
- 92,36,28,137,214,137,252,239,232,251,1,15,139,149,233,252,233,244,2,248,82,
- 129,252,248,239,15,130,244,70,255,15,132,244,248,248,1,129,122,253,4,239,
- 15,133,244,70,139,108,36,24,137,149,233,137,149,233,139,90,252,252,139,50,
- 141,82,8,137,252,239,137,92,36,28,232,251,1,16,139,149,233,133,192,15,132,
- 244,249,72,139,106,8,72,139,66,16,72,137,106,252,248,72,137,2,248,83,184,
- 237,252,233,244,84,248,2,199,66,12,237,252,233,244,1,248,3,255,199,66,252,
- 252,237,252,233,244,73,248,85,129,252,248,239,15,130,244,70,139,42,129,122,
- 253,4,239,15,133,244,70,255,131,189,233,0,15,133,244,70,255,139,106,252,248,
- 139,133,233,139,90,252,252,199,66,252,252,237,137,66,252,248,199,66,12,237,
- 184,237,252,233,244,84,248,86,129,252,248,239,15,130,244,70,129,122,253,4,
- 239,15,133,244,70,129,122,253,12,239,15,133,244,70,139,90,252,252,139,66,
- 8,131,192,1,199,66,252,252,237,137,66,252,248,139,42,59,133,233,15,131,244,
- 248,255,193,224,3,3,133,233,248,1,129,120,253,4,239,15,132,244,87,72,139,
- 40,72,137,42,252,233,244,83,248,2,131,189,233,0,15,132,244,87,137,252,239,
- 137,213,137,198,232,251,1,3,137,252,234,133,192,15,133,244,1,248,87,184,237,
- 252,233,244,84,248,88,129,252,248,239,15,130,244,70,255,139,106,252,248,139,
- 133,233,139,90,252,252,199,66,252,252,237,137,66,252,248,199,66,12,237,199,
- 66,8,0,0,0,0,184,237,252,233,244,84,248,89,129,252,248,239,15,130,244,70,
- 141,74,8,131,232,1,187,237,248,1,65,15,182,174,233,193,252,237,235,131,229,
- 1,1,252,235,252,233,244,29,248,90,129,252,248,239,15,130,244,70,255,129,122,
- 253,12,239,15,133,244,70,139,106,4,137,106,12,199,66,4,237,139,42,139,90,
- 8,137,106,8,137,26,141,74,16,131,232,2,187,237,252,233,244,1,248,91,129,252,
- 248,239,15,130,244,70,139,42,139,90,252,252,137,92,36,28,137,44,36,129,122,
- 253,4,239,15,133,244,70,72,131,189,233,0,15,133,244,70,128,189,233,235,15,
- 135,244,70,255,139,141,233,15,132,244,247,59,141,233,15,132,244,70,248,1,
- 141,92,193,252,240,59,157,233,15,135,244,70,137,157,233,139,108,36,24,137,
- 149,233,131,194,8,137,149,233,141,108,194,232,72,41,221,57,203,15,132,244,
- 249,248,2,72,139,4,43,72,137,67,252,248,131,252,235,8,57,203,15,133,244,2,
- 248,3,137,206,139,60,36,232,244,26,255,139,108,36,24,139,28,36,139,149,233,
- 65,137,174,233,65,199,134,233,237,129,252,248,239,15,135,244,254,248,4,139,
- 139,233,68,139,187,233,137,139,233,68,137,252,251,41,203,15,132,244,252,141,
- 4,26,193,252,235,3,59,133,233,15,135,244,255,137,213,72,41,205,248,5,72,139,
- 1,72,137,4,41,131,193,8,68,57,252,249,15,133,244,5,248,6,255,141,67,2,199,
- 66,252,252,237,248,7,139,92,36,28,137,68,36,4,72,199,193,252,248,252,255,
- 252,255,252,255,252,247,195,237,15,132,244,14,252,233,244,15,248,8,199,66,
- 252,252,237,139,139,233,131,252,233,8,137,139,233,72,139,1,72,137,2,184,237,
- 252,233,244,7,248,9,139,12,36,68,137,185,233,137,222,137,252,239,232,251,
- 1,0,139,28,36,139,149,233,252,233,244,4,248,92,255,139,106,252,248,139,173,
- 233,139,90,252,252,137,92,36,28,137,44,36,72,131,189,233,0,15,133,244,70,
- 128,189,233,235,15,135,244,70,139,141,233,15,132,244,247,59,141,233,15,132,
- 244,70,248,1,141,92,193,252,248,59,157,233,15,135,244,70,137,157,233,139,
- 108,36,24,137,149,233,255,137,149,233,141,108,194,252,240,72,41,221,57,203,
- 15,132,244,249,248,2,72,139,4,43,72,137,67,252,248,131,252,235,8,57,203,15,
- 133,244,2,248,3,137,206,139,60,36,232,244,26,139,108,36,24,139,28,36,139,
- 149,233,65,137,174,233,65,199,134,233,237,129,252,248,239,15,135,244,254,
- 248,4,139,139,233,68,139,187,233,137,139,233,255,68,137,252,251,41,203,15,
- 132,244,252,141,4,26,193,252,235,3,59,133,233,15,135,244,255,137,213,72,41,
- 205,248,5,72,139,1,72,137,4,41,131,193,8,68,57,252,249,15,133,244,5,248,6,
- 141,67,1,248,7,139,92,36,28,137,68,36,4,49,201,252,247,195,237,15,132,244,
- 14,252,233,244,15,248,8,137,222,137,252,239,232,251,1,17,248,9,139,12,36,
- 68,137,185,233,137,222,137,252,239,232,251,1,0,139,28,36,139,149,233,252,
- 233,244,4,248,93,255,139,108,36,24,72,252,247,133,233,237,15,132,244,70,137,
- 149,233,141,68,194,252,248,137,133,233,49,192,72,137,133,233,176,235,136,
- 133,233,252,233,244,17,248,94,139,90,252,252,221,90,252,248,252,233,244,73,
- 248,95,129,252,248,239,15,130,244,70,129,122,253,4,239,15,133,244,248,255,
- 139,42,131,252,253,0,15,137,244,78,252,247,221,15,136,244,247,248,96,248,
- 78,139,90,252,252,199,66,252,252,237,137,106,252,248,252,233,244,73,248,1,
- 139,90,252,252,199,66,252,252,0,0,224,65,199,66,252,248,0,0,0,0,252,233,244,
- 73,248,2,15,135,244,70,252,242,15,16,2,72,184,237,237,102,72,15,110,200,15,
- 84,193,248,79,139,90,252,252,252,242,15,17,66,252,248,248,73,184,237,248,
- 84,255,137,68,36,4,248,71,252,247,195,237,15,133,244,253,248,5,56,67,252,
- 255,15,135,244,252,15,182,75,252,253,72,252,247,209,141,20,202,139,3,15,182,
- 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,6,199,68,194,
- 252,244,237,131,192,1,252,233,244,5,248,7,72,199,193,252,248,252,255,252,
- 255,252,255,252,233,244,15,248,97,129,122,253,4,239,15,133,244,247,139,42,
- 252,233,244,78,248,1,255,15,135,244,70,252,242,15,16,2,232,244,98,252,242,
- 15,44,232,129,252,253,0,0,0,128,15,133,244,78,252,242,15,42,205,102,15,46,
- 193,15,138,244,79,15,132,244,78,252,233,244,79,248,99,129,122,253,4,239,15,
- 133,244,247,139,42,252,233,244,78,248,1,15,135,244,70,255,252,242,15,16,2,
- 232,244,100,252,242,15,44,232,129,252,253,0,0,0,128,15,133,244,78,252,242,
- 15,42,205,102,15,46,193,15,138,244,79,15,132,244,78,252,233,244,79,248,101,
- 129,252,248,239,15,130,244,70,129,122,253,4,239,15,131,244,70,252,242,15,
- 81,2,252,233,244,79,248,102,255,129,252,248,239,15,133,244,70,129,122,253,
- 4,239,15,131,244,70,252,242,15,16,2,137,213,232,251,1,18,137,252,234,252,
- 233,244,79,248,103,129,252,248,239,15,130,244,70,129,122,253,4,239,15,131,
- 244,70,252,242,15,16,2,137,213,232,251,1,19,137,252,234,252,233,244,79,248,
- 104,129,252,248,239,15,130,244,70,255,129,122,253,4,239,15,131,244,70,252,
- 242,15,16,2,137,213,232,251,1,20,137,252,234,252,233,244,79,248,105,129,252,
- 248,239,15,130,244,70,129,122,253,4,239,15,131,244,70,252,242,15,16,2,137,
- 213,232,251,1,21,137,252,234,252,233,244,79,248,106,129,252,248,239,15,130,
- 244,70,129,122,253,4,239,15,131,244,70,255,252,242,15,16,2,137,213,232,251,
- 1,22,137,252,234,252,233,244,79,248,107,129,252,248,239,15,130,244,70,129,
- 122,253,4,239,15,131,244,70,252,242,15,16,2,137,213,232,251,1,23,137,252,
- 234,252,233,244,79,248,108,129,252,248,239,15,130,244,70,129,122,253,4,239,
- 15,131,244,70,252,242,15,16,2,137,213,232,251,1,24,137,252,234,252,233,244,
- 79,248,109,255,129,252,248,239,15,130,244,70,129,122,253,4,239,15,131,244,
- 70,252,242,15,16,2,137,213,232,251,1,25,137,252,234,252,233,244,79,248,110,
- 129,252,248,239,15,130,244,70,129,122,253,4,239,15,131,244,70,252,242,15,
- 16,2,137,213,232,251,1,26,137,252,234,252,233,244,79,248,111,129,252,248,
- 239,15,130,244,70,255,129,122,253,4,239,15,131,244,70,252,242,15,16,2,137,
- 213,232,251,1,27,137,252,234,252,233,244,79,248,112,129,252,248,239,15,130,
- 244,70,129,122,253,4,239,15,131,244,70,252,242,15,16,2,137,213,232,251,1,
- 28,137,252,234,252,233,244,79,248,113,129,252,248,239,15,130,244,70,129,122,
- 253,4,239,15,131,244,70,255,252,242,15,16,2,137,213,232,251,1,29,137,252,
- 234,252,233,244,79,248,114,129,252,248,239,15,130,244,70,129,122,253,4,239,
- 15,131,244,70,129,122,253,12,239,15,131,244,70,252,242,15,16,2,252,242,15,
- 16,74,8,137,213,232,251,1,30,137,252,234,252,233,244,79,248,115,129,252,248,
- 239,15,130,244,70,129,122,253,4,239,15,131,244,70,255,129,122,253,12,239,
- 15,131,244,70,252,242,15,16,2,252,242,15,16,74,8,137,213,232,251,1,31,137,
- 252,234,252,233,244,79,248,116,129,252,248,239,15,130,244,70,129,122,253,
- 4,239,15,131,244,70,129,122,253,12,239,15,131,244,70,252,242,15,16,2,252,
- 242,15,16,74,8,137,213,232,251,1,32,137,252,234,252,233,244,79,248,117,129,
- 252,248,239,15,130,244,70,255,129,122,253,4,239,15,131,244,70,129,122,253,
- 12,239,15,131,244,70,221,66,8,221,2,217,252,253,221,217,252,233,244,94,248,
- 118,129,252,248,239,15,130,244,70,139,106,4,129,252,253,239,15,131,244,70,
- 139,90,252,252,139,2,137,106,252,252,137,66,252,248,209,229,129,252,253,0,
- 0,224,252,255,15,131,244,249,9,232,15,132,244,249,184,252,254,3,0,0,129,252,
- 253,0,0,32,0,15,130,244,250,248,1,255,193,252,237,21,41,197,252,242,15,42,
- 197,139,106,252,252,129,229,252,255,252,255,15,128,129,205,0,0,224,63,137,
- 106,252,252,248,2,252,242,15,17,2,184,237,252,233,244,84,248,3,15,87,192,
- 252,233,244,2,248,4,252,242,15,16,2,72,189,237,237,102,72,15,110,205,252,
- 242,15,89,193,252,242,15,17,66,252,248,139,106,252,252,184,52,4,0,0,209,229,
- 252,233,244,1,248,119,129,252,248,239,15,130,244,70,129,122,253,4,239,15,
- 131,244,70,252,242,15,16,2,139,106,4,139,90,252,252,209,229,129,252,253,0,
- 0,224,252,255,15,132,244,250,255,15,40,224,232,244,120,252,242,15,92,224,
- 248,1,252,242,15,17,66,252,248,252,242,15,17,34,139,66,252,252,139,106,4,
- 49,232,15,136,244,249,248,2,184,237,252,233,244,84,248,3,129,252,245,0,0,
- 0,128,137,106,4,252,233,244,2,248,4,15,87,228,252,233,244,1,248,121,185,2,
- 0,0,0,129,122,253,4,239,15,133,244,250,139,42,248,1,255,57,193,15,131,244,
- 78,129,124,253,202,252,252,239,15,133,244,249,59,108,202,252,248,15,79,108,
- 202,252,248,131,193,1,252,233,244,1,248,3,15,135,244,70,252,242,15,42,197,
- 252,233,244,252,248,4,15,135,244,70,252,242,15,16,2,248,5,57,193,15,131,244,
- 79,129,124,253,202,252,252,239,15,130,244,252,255,15,135,244,70,252,242,15,
- 42,76,202,252,248,252,233,244,253,248,6,252,242,15,16,76,202,252,248,248,
- 7,252,242,15,93,193,131,193,1,252,233,244,5,248,122,185,2,0,0,0,129,122,253,
- 4,239,15,133,244,250,139,42,248,1,57,193,15,131,244,78,129,124,253,202,252,
- 252,239,15,133,244,249,59,108,202,252,248,15,76,108,202,252,248,131,193,1,
- 252,233,244,1,248,3,255,15,135,244,70,252,242,15,42,197,252,233,244,252,248,
- 4,15,135,244,70,252,242,15,16,2,248,5,57,193,15,131,244,79,129,124,253,202,
- 252,252,239,15,130,244,252,15,135,244,70,252,242,15,42,76,202,252,248,252,
- 233,244,253,248,6,252,242,15,16,76,202,252,248,248,7,252,242,15,95,193,131,
- 193,1,252,233,244,5,248,123,255,129,252,248,239,15,133,244,70,129,122,253,
- 4,239,15,133,244,70,139,42,139,90,252,252,131,189,233,1,15,130,244,87,15,
- 182,173,233,252,233,244,78,248,124,65,139,174,233,65,59,174,233,15,130,244,
- 247,232,244,81,248,1,255,129,252,248,239,15,133,244,70,129,122,253,4,239,
- 15,133,244,70,139,42,129,252,253,252,255,0,0,0,15,135,244,70,137,108,36,4,
- 199,68,36,8,1,0,0,0,72,141,68,36,4,248,125,139,108,36,24,137,149,233,139,
- 84,36,8,72,137,198,137,252,239,137,92,36,28,232,251,1,33,248,126,139,149,
- 233,139,90,252,252,199,66,252,252,237,137,66,252,248,252,233,244,73,248,127,
- 65,139,174,233,65,59,174,233,15,130,244,247,255,232,244,81,248,1,199,68,36,
- 4,252,255,252,255,252,255,252,255,129,252,248,239,15,130,244,70,15,134,244,
- 247,129,122,253,20,239,15,133,244,70,139,106,16,137,108,36,4,248,1,129,122,
- 253,4,239,15,133,244,70,129,122,253,12,239,15,133,244,70,139,42,137,108,36,
- 8,139,173,233,139,74,8,139,68,36,4,57,197,15,130,244,251,248,2,255,133,201,
- 15,142,244,253,248,3,139,108,36,8,41,200,15,140,244,128,141,172,253,13,233,
- 131,192,1,248,4,137,68,36,8,137,232,252,233,244,125,248,5,15,140,244,252,
- 141,68,40,1,252,233,244,2,248,6,137,232,252,233,244,2,248,7,15,132,244,254,
- 255,1,252,233,131,193,1,15,143,244,3,248,8,185,1,0,0,0,252,233,244,3,248,
- 128,49,192,252,233,244,4,248,129,129,252,248,239,15,130,244,70,65,139,174,
- 233,65,59,174,233,15,130,244,247,232,244,81,248,1,129,122,253,4,239,255,15,
- 133,244,70,139,108,36,24,65,141,190,233,137,149,233,139,50,139,135,233,137,
- 175,233,137,135,233,137,92,36,28,232,251,1,34,137,199,232,251,1,35,252,233,
- 244,126,248,130,129,252,248,239,15,130,244,70,65,139,174,233,65,59,174,233,
- 15,130,244,247,232,244,81,248,1,255,129,122,253,4,239,15,133,244,70,139,108,
- 36,24,65,141,190,233,137,149,233,139,50,139,135,233,137,175,233,137,135,233,
- 137,92,36,28,232,251,1,36,137,199,232,251,1,35,252,233,244,126,248,131,129,
- 252,248,239,15,130,244,70,65,139,174,233,65,59,174,233,15,130,244,247,232,
- 244,81,248,1,255,129,122,253,4,239,15,133,244,70,139,108,36,24,65,141,190,
- 233,137,149,233,139,50,139,135,233,137,175,233,137,135,233,137,92,36,28,232,
- 251,1,37,137,199,232,251,1,35,252,233,244,126,248,132,129,252,248,239,15,
- 130,244,70,129,122,253,4,239,15,133,244,247,139,42,252,233,244,96,248,1,255,
- 15,135,244,70,252,242,15,16,2,72,189,237,237,102,72,15,110,205,252,242,15,
- 88,193,102,15,126,197,248,2,252,233,244,96,248,133,129,252,248,239,15,130,
- 244,70,72,189,237,237,102,72,15,110,205,129,122,253,4,239,15,133,244,247,
- 139,42,252,233,244,248,248,1,15,135,244,70,255,252,242,15,16,2,252,242,15,
- 88,193,102,15,126,197,248,2,137,68,36,4,141,68,194,252,240,248,1,57,208,15,
- 134,244,96,129,120,253,4,239,15,133,244,248,35,40,131,232,8,252,233,244,1,
- 248,2,15,135,244,134,252,242,15,16,0,252,242,15,88,193,102,15,126,193,33,
- 205,131,232,8,252,233,244,1,248,135,129,252,248,239,15,130,244,70,72,189,
- 237,237,255,102,72,15,110,205,129,122,253,4,239,15,133,244,247,139,42,252,
- 233,244,248,248,1,15,135,244,70,252,242,15,16,2,252,242,15,88,193,102,15,
- 126,197,248,2,137,68,36,4,141,68,194,252,240,248,1,57,208,15,134,244,96,129,
- 120,253,4,239,15,133,244,248,11,40,131,232,8,252,233,244,1,248,2,15,135,244,
- 134,255,252,242,15,16,0,252,242,15,88,193,102,15,126,193,9,205,131,232,8,
- 252,233,244,1,248,136,129,252,248,239,15,130,244,70,72,189,237,237,102,72,
- 15,110,205,129,122,253,4,239,15,133,244,247,139,42,252,233,244,248,248,1,
- 15,135,244,70,252,242,15,16,2,252,242,15,88,193,102,15,126,197,248,2,137,
- 68,36,4,141,68,194,252,240,248,1,57,208,15,134,244,96,255,129,120,253,4,239,
- 15,133,244,248,51,40,131,232,8,252,233,244,1,248,2,15,135,244,134,252,242,
- 15,16,0,252,242,15,88,193,102,15,126,193,49,205,131,232,8,252,233,244,1,248,
- 137,129,252,248,239,15,130,244,70,129,122,253,4,239,15,133,244,247,139,42,
- 252,233,244,248,248,1,255,15,135,244,70,252,242,15,16,2,72,189,237,237,102,
- 72,15,110,205,252,242,15,88,193,102,15,126,197,248,2,15,205,252,233,244,96,
- 248,138,129,252,248,239,15,130,244,70,129,122,253,4,239,15,133,244,247,139,
- 42,252,233,244,248,248,1,15,135,244,70,252,242,15,16,2,72,189,237,237,255,
- 102,72,15,110,205,252,242,15,88,193,102,15,126,197,248,2,252,247,213,252,
- 233,244,96,248,134,139,68,36,4,252,233,244,70,248,139,129,252,248,239,15,
- 130,244,70,129,122,253,4,239,15,133,244,247,139,42,252,233,244,248,248,1,
- 15,135,244,70,252,242,15,16,2,72,189,237,237,255,102,72,15,110,205,252,242,
- 15,88,193,102,15,126,197,248,2,129,122,253,12,239,15,133,244,70,139,74,8,
- 211,229,252,233,244,96,248,140,129,252,248,239,15,130,244,70,129,122,253,
- 4,239,15,133,244,247,139,42,252,233,244,248,248,1,15,135,244,70,252,242,15,
- 16,2,72,189,237,237,255,102,72,15,110,205,252,242,15,88,193,102,15,126,197,
- 248,2,129,122,253,12,239,15,133,244,70,139,74,8,211,252,237,252,233,244,96,
- 248,141,129,252,248,239,15,130,244,70,129,122,253,4,239,15,133,244,247,139,
- 42,252,233,244,248,248,1,15,135,244,70,252,242,15,16,2,72,189,237,237,255,
- 102,72,15,110,205,252,242,15,88,193,102,15,126,197,248,2,129,122,253,12,239,
- 15,133,244,70,139,74,8,211,252,253,252,233,244,96,248,142,129,252,248,239,
- 15,130,244,70,129,122,253,4,239,15,133,244,247,139,42,252,233,244,248,248,
- 1,15,135,244,70,252,242,15,16,2,72,189,237,237,255,102,72,15,110,205,252,
- 242,15,88,193,102,15,126,197,248,2,129,122,253,12,239,15,133,244,70,139,74,
- 8,211,197,252,233,244,96,248,143,129,252,248,239,15,130,244,70,129,122,253,
- 4,239,15,133,244,247,139,42,252,233,244,248,248,1,15,135,244,70,252,242,15,
- 16,2,72,189,237,237,255,102,72,15,110,205,252,242,15,88,193,102,15,126,197,
- 248,2,129,122,253,12,239,15,133,244,70,139,74,8,211,205,252,233,244,96,248,
- 144,184,237,252,233,244,70,248,145,184,237,248,70,139,108,36,24,139,90,252,
- 252,137,92,36,28,137,149,233,141,68,194,252,248,141,136,233,137,133,233,139,
- 66,252,248,59,141,233,15,135,244,251,137,252,239,252,255,144,233,255,139,
- 149,233,133,192,15,143,244,84,248,1,139,141,233,41,209,193,252,233,3,133,
- 192,141,65,1,139,106,252,248,15,133,244,34,139,157,233,139,11,15,182,252,
- 233,15,182,205,131,195,4,65,252,255,36,252,238,248,34,137,209,252,247,195,
- 237,15,133,244,249,15,182,107,252,253,72,252,247,213,141,20,252,234,252,233,
- 244,29,248,3,137,221,131,229,252,248,41,252,234,252,233,244,29,248,5,190,
- 237,137,252,239,232,251,1,0,139,149,233,255,49,192,252,233,244,1,248,81,93,
- 72,137,108,36,8,139,108,36,24,137,92,36,28,137,149,233,141,68,194,252,248,
- 137,252,239,137,133,233,232,251,1,38,139,149,233,139,133,233,41,208,193,232,
- 3,131,192,1,72,139,108,36,8,85,195,248,146,65,15,182,134,233,168,235,15,133,
- 244,251,168,235,15,133,244,247,168,235,15,132,244,247,65,252,255,142,233,
- 252,233,244,247,248,147,255,65,15,182,134,233,168,235,15,133,244,251,252,
- 233,244,247,248,148,65,15,182,134,233,168,235,15,133,244,251,168,235,15,132,
- 244,251,65,252,255,142,233,15,132,244,247,168,235,15,132,244,251,248,1,255,
- 139,108,36,24,137,149,233,137,222,137,252,239,232,251,1,39,248,3,139,149,
- 233,248,4,15,182,75,252,253,248,5,15,182,107,252,252,15,183,67,252,254,65,
- 252,255,164,253,252,238,233,248,149,131,195,4,139,77,232,137,76,36,4,252,
- 233,244,4,248,150,139,106,252,248,139,173,233,15,182,133,233,141,4,194,139,
- 108,36,24,137,149,233,137,133,233,137,222,65,141,190,233,73,137,174,233,137,
- 92,36,28,232,251,1,40,252,233,244,3,248,151,137,92,36,28,252,233,244,247,
- 248,152,255,137,92,36,28,131,203,1,248,1,141,68,194,252,248,139,108,36,24,
- 137,149,233,137,133,233,137,222,137,252,239,232,251,1,41,199,68,36,28,0,0,
- 0,0,131,227,252,254,139,149,233,72,137,193,139,133,233,41,208,72,137,205,
- 15,182,75,252,253,193,232,3,131,192,1,252,255,229,248,153,139,77,232,137,
- 12,36,68,137,116,36,8,68,139,116,36,4,15,182,75,252,253,141,12,202,65,131,
- 252,238,1,15,132,244,248,248,1,72,139,40,72,137,41,131,192,8,131,193,8,65,
- 131,252,238,1,15,133,244,1,248,2,15,182,67,252,253,15,182,107,252,255,1,232,
- 141,68,194,252,248,248,3,57,200,15,135,244,255,68,139,116,36,8,139,44,36,
- 65,139,142,233,139,4,169,133,192,15,132,244,47,15,183,128,233,57,232,15,132,
- 244,47,255,133,192,15,133,245,65,137,174,233,139,108,36,24,137,149,233,137,
- 222,65,141,190,233,73,137,174,233,232,251,1,42,139,149,233,252,233,244,47,
- 248,9,199,65,4,237,131,193,8,252,233,244,3,248,154,255,139,108,36,24,137,
- 149,233,137,222,137,252,239,232,251,1,43,139,149,233,131,252,235,4,252,233,
- 244,47,255,248,155,65,85,65,84,65,83,65,82,65,81,65,80,87,86,85,72,141,108,
- 36,88,85,83,82,81,80,15,182,69,252,248,138,101,252,240,76,137,125,252,248,
- 76,137,117,252,240,68,139,117,0,65,139,142,233,65,199,134,233,237,65,137,
- 134,233,65,137,142,233,72,129,252,236,239,72,131,197,128,252,242,68,15,17,
- 125,252,248,252,242,68,15,17,117,252,240,252,242,68,15,17,109,232,252,242,
- 68,15,17,101,224,252,242,68,15,17,93,216,252,242,68,15,17,85,208,252,242,
- 68,15,17,77,200,252,242,68,15,17,69,192,252,242,15,17,125,184,252,242,15,
- 17,117,176,252,242,15,17,109,168,252,242,15,17,101,160,252,242,15,17,93,152,
- 252,242,15,17,85,144,252,242,15,17,77,136,252,242,15,17,69,128,65,139,174,
- 233,65,139,150,233,73,137,174,233,137,149,233,72,137,230,65,141,190,233,65,
- 199,134,233,0,0,0,0,232,251,1,44,72,139,141,233,72,129,225,239,72,137,204,
- 137,169,233,139,149,233,139,153,233,252,233,244,247,248,156,255,72,131,196,
- 16,248,1,76,139,108,36,8,76,139,36,36,255,139,124,36,24,137,151,233,137,197,
- 137,28,36,137,218,65,139,182,233,232,251,1,45,139,28,36,137,232,139,108,36,
- 24,139,149,233,255,133,192,15,136,244,255,139,108,36,24,137,68,36,4,68,139,
- 122,252,248,69,139,191,233,69,139,191,233,137,149,233,65,199,134,233,0,0,
- 0,0,65,199,134,233,237,139,3,15,182,204,15,182,232,131,195,4,193,232,16,129,
- 252,253,239,15,130,244,249,129,252,253,239,15,131,244,250,248,2,139,68,36,
- 4,248,3,65,252,255,36,252,238,248,4,139,66,252,252,169,237,15,133,244,2,255,
- 15,182,64,252,253,72,252,247,208,68,139,124,194,252,248,69,139,191,233,69,
- 139,191,233,252,233,244,2,248,9,252,247,216,137,252,239,137,198,232,251,1,
- 1,248,157,248,98,72,184,237,237,102,72,15,110,208,72,184,237,237,102,72,15,
- 110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102,15,85,208,
- 252,242,15,88,203,252,242,15,92,203,102,15,86,202,72,184,237,237,102,72,15,
- 110,208,252,242,15,194,193,1,102,15,84,194,252,242,15,92,200,15,40,193,248,
- 1,195,248,158,248,100,72,184,237,237,255,102,72,15,110,208,72,184,237,237,
- 102,72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244,247,102,
- 15,85,208,252,242,15,88,203,252,242,15,92,203,102,15,86,202,72,184,237,237,
- 102,72,15,110,208,252,242,15,194,193,6,102,15,84,194,252,242,15,92,200,15,
- 40,193,248,1,195,248,159,248,120,72,184,237,237,102,72,15,110,208,72,184,
- 237,237,102,72,15,110,216,15,40,200,102,15,84,202,102,15,46,217,15,134,244,
- 247,102,15,85,208,15,40,193,252,242,15,88,203,252,242,15,92,203,72,184,237,
- 237,102,72,15,110,216,252,242,15,194,193,1,102,15,84,195,252,242,15,92,200,
- 102,15,86,202,15,40,193,248,1,195,248,160,15,40,232,252,242,15,94,193,72,
- 184,237,237,255,102,72,15,110,208,72,184,237,237,102,72,15,110,216,15,40,
- 224,102,15,84,226,102,15,46,220,15,134,244,247,102,15,85,208,252,242,15,88,
- 227,252,242,15,92,227,102,15,86,226,72,184,237,237,102,72,15,110,208,252,
- 242,15,194,196,1,102,15,84,194,252,242,15,92,224,15,40,197,252,242,15,89,
- 204,252,242,15,92,193,195,248,1,252,242,15,89,200,15,40,197,252,242,15,92,
- 193,195,248,161,131,252,248,1,15,142,244,252,248,1,169,1,0,0,0,15,133,244,
- 248,252,242,15,89,192,209,232,252,233,244,1,248,2,209,232,15,132,244,251,
- 15,40,200,248,3,252,242,15,89,192,209,232,15,132,244,250,255,15,131,244,3,
- 252,242,15,89,200,252,233,244,3,248,4,252,242,15,89,193,248,5,195,248,6,15,
- 132,244,5,15,130,244,253,252,247,216,232,244,1,72,184,237,237,102,72,15,110,
- 200,252,242,15,94,200,15,40,193,195,248,7,72,184,237,237,102,72,15,110,192,
- 195,248,162,137,252,248,83,15,162,137,6,137,94,4,137,78,8,137,86,12,91,195,
- 248,163,255,204,255,204,248,164,83,65,87,65,86,72,131,252,236,40,68,141,181,
- 233,139,157,233,15,183,192,137,131,233,72,137,187,233,72,137,179,233,72,137,
- 147,233,72,137,139,233,252,242,15,17,131,233,252,242,15,17,139,233,252,242,
- 15,17,147,233,252,242,15,17,155,233,72,141,132,253,36,233,76,137,131,233,
- 76,137,139,233,252,242,15,17,163,233,252,242,15,17,171,233,252,242,15,17,
- 179,233,252,242,15,17,187,233,72,137,131,233,255,72,137,230,137,92,36,28,
- 137,223,232,251,1,46,65,199,134,233,237,139,144,233,139,128,233,41,208,139,
- 106,252,248,193,232,3,131,192,1,139,157,233,139,11,15,182,252,233,15,182,
- 205,131,195,4,65,252,255,36,252,238,248,33,139,76,36,24,65,139,158,233,72,
- 137,139,233,137,145,233,137,169,233,137,223,137,198,232,251,1,47,72,139,131,
- 233,252,242,15,16,131,233,252,233,244,17,248,165,85,72,137,229,83,72,137,
- 252,251,139,131,233,72,41,196,15,182,139,233,131,252,233,1,15,136,244,248,
- 248,1,255,72,139,132,253,203,233,72,137,132,253,204,233,131,252,233,1,15,
- 137,244,1,248,2,15,182,131,233,72,139,187,233,72,139,179,233,72,139,147,233,
- 72,139,139,233,76,139,131,233,76,139,139,233,133,192,15,132,244,251,15,40,
- 131,233,15,40,139,233,15,40,147,233,15,40,155,233,131,252,248,4,15,134,244,
- 251,255,15,40,163,233,15,40,171,233,15,40,179,233,15,40,187,233,248,5,252,
- 255,147,233,72,137,131,233,15,41,131,233,72,137,147,233,15,41,139,233,72,
- 139,93,252,248,201,195,255,249,255,129,124,253,202,4,239,15,133,244,253,129,
- 124,253,194,4,239,15,133,244,254,139,44,202,131,195,4,59,44,194,255,15,141,
- 244,255,255,15,140,244,255,255,15,143,244,255,255,15,142,244,255,255,248,
- 6,15,183,67,252,254,141,156,253,131,233,248,9,139,3,15,182,204,15,182,232,
- 131,195,4,193,232,16,65,252,255,36,252,238,248,7,15,135,244,50,129,124,253,
- 194,4,239,15,130,244,247,15,133,244,50,252,242,15,42,4,194,252,233,244,248,
- 248,8,15,135,244,50,252,242,15,42,12,202,252,242,15,16,4,194,131,195,4,102,
- 15,46,193,255,15,134,244,9,255,15,135,244,9,255,15,130,244,9,255,15,131,244,
- 9,255,252,233,244,6,248,1,252,242,15,16,4,194,248,2,131,195,4,102,15,46,4,
- 202,248,3,255,252,233,244,6,255,139,108,194,4,131,195,4,129,252,253,239,15,
- 133,244,253,129,124,253,202,4,239,15,133,244,254,139,44,194,59,44,202,255,
- 15,133,244,255,255,15,132,244,255,255,15,183,67,252,254,141,156,253,131,233,
- 248,9,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,
- 238,248,7,15,135,244,251,129,124,253,202,4,239,15,130,244,247,15,133,244,
- 251,252,242,15,42,4,202,252,233,244,248,248,8,15,135,244,251,252,242,15,42,
- 4,194,102,15,46,4,202,252,233,244,250,248,1,252,242,15,16,4,202,248,2,102,
- 15,46,4,194,248,4,255,15,138,244,248,15,133,244,248,255,15,138,244,248,15,
- 132,244,247,255,248,1,15,183,67,252,254,141,156,253,131,233,248,2,255,248,
- 2,15,183,67,252,254,141,156,253,131,233,248,1,255,252,233,244,9,255,139,3,
- 15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,248,
- 5,129,252,253,239,15,132,244,55,129,124,253,202,4,239,15,132,244,55,57,108,
- 202,4,15,133,244,2,129,252,253,239,15,131,244,1,139,12,202,139,4,194,57,193,
- 15,132,244,1,129,252,253,239,15,135,244,2,129,252,253,239,15,130,244,2,255,
- 139,169,233,133,252,237,15,132,244,2,252,246,133,233,235,15,133,244,2,255,
- 49,252,237,255,189,1,0,0,0,255,252,233,244,54,255,248,3,129,252,253,239,255,
- 15,133,244,9,255,252,233,244,55,255,72,252,247,208,139,108,202,4,131,195,
- 4,129,252,253,239,15,133,244,249,139,12,202,65,59,12,135,255,139,108,202,
- 4,131,195,4,129,252,253,239,15,133,244,253,65,129,124,253,199,4,239,15,133,
- 244,254,65,139,44,199,59,44,202,255,15,183,67,252,254,141,156,253,131,233,
- 248,9,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,
- 238,248,7,15,135,244,249,65,129,124,253,199,4,239,15,130,244,247,252,242,
- 65,15,42,4,199,252,233,244,248,248,8,252,242,15,42,4,202,102,65,15,46,4,199,
- 252,233,244,250,248,1,252,242,65,15,16,4,199,248,2,102,15,46,4,202,248,4,
- 255,72,252,247,208,139,108,202,4,131,195,4,57,197,255,15,133,244,249,15,183,
- 67,252,254,141,156,253,131,233,248,2,139,3,15,182,204,15,182,232,131,195,
- 4,193,232,16,65,252,255,36,252,238,248,3,129,252,253,239,15,133,244,2,252,
- 233,244,55,255,15,132,244,248,129,252,253,239,15,132,244,55,15,183,67,252,
- 254,141,156,253,131,233,248,2,139,3,15,182,204,15,182,232,131,195,4,193,232,
- 16,65,252,255,36,252,238,255,139,108,194,4,131,195,4,129,252,253,239,255,
- 15,131,244,247,255,137,108,202,4,139,44,194,137,44,202,255,15,183,67,252,
- 254,141,156,253,131,233,248,1,139,3,15,182,204,15,182,232,131,195,4,193,232,
- 16,65,252,255,36,252,238,255,3,68,202,4,15,133,244,56,139,3,15,182,204,15,
- 182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,129,124,253,202,4,
- 239,15,131,244,56,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,
- 255,36,252,238,255,72,139,44,194,72,137,44,202,139,3,15,182,204,15,182,232,
- 131,195,4,193,232,16,65,252,255,36,252,238,255,49,252,237,129,124,253,194,
- 4,239,129,213,239,137,108,202,4,139,3,15,182,204,15,182,232,131,195,4,193,
- 232,16,65,252,255,36,252,238,255,129,124,253,194,4,239,15,133,244,251,139,
- 44,194,252,247,221,15,128,244,250,199,68,202,4,237,137,44,202,248,9,139,3,
- 15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,4,199,
- 68,202,4,0,0,224,65,199,4,202,0,0,0,0,252,233,244,9,248,5,15,135,244,61,252,
- 242,15,16,4,194,72,184,237,237,102,72,15,110,200,15,87,193,252,242,15,17,
- 4,202,252,233,244,9,255,129,124,253,194,4,239,15,133,244,248,139,4,194,139,
- 128,233,248,1,199,68,202,4,237,137,4,202,139,3,15,182,204,15,182,232,131,
- 195,4,193,232,16,65,252,255,36,252,238,248,2,129,124,253,194,4,239,15,133,
- 244,64,139,60,194,255,139,175,233,131,252,253,0,15,133,244,255,248,3,255,
- 248,65,137,213,232,251,1,48,137,252,234,15,182,75,252,253,252,233,244,1,255,
- 248,9,252,246,133,233,235,15,133,244,3,252,233,244,64,255,15,182,252,236,
- 15,182,192,255,129,124,253,252,234,4,239,15,133,244,58,65,129,124,253,199,
- 4,239,15,133,244,58,139,44,252,234,65,3,44,199,15,128,244,57,255,129,124,
- 253,252,234,4,239,15,133,244,60,65,129,124,253,199,4,239,15,133,244,60,65,
- 139,4,199,3,4,252,234,15,128,244,59,255,129,124,253,252,234,4,239,15,133,
- 244,63,129,124,253,194,4,239,15,133,244,63,139,44,252,234,3,44,194,15,128,
- 244,62,255,199,68,202,4,237,255,137,4,202,255,129,124,253,252,234,4,239,15,
- 133,244,58,65,129,124,253,199,4,239,15,133,244,58,139,44,252,234,65,43,44,
- 199,15,128,244,57,255,129,124,253,252,234,4,239,15,133,244,60,65,129,124,
- 253,199,4,239,15,133,244,60,65,139,4,199,43,4,252,234,15,128,244,59,255,129,
- 124,253,252,234,4,239,15,133,244,63,129,124,253,194,4,239,15,133,244,63,139,
- 44,252,234,43,44,194,15,128,244,62,255,129,124,253,252,234,4,239,15,133,244,
- 58,65,129,124,253,199,4,239,15,133,244,58,139,44,252,234,65,15,175,44,199,
- 15,128,244,57,255,129,124,253,252,234,4,239,15,133,244,60,65,129,124,253,
- 199,4,239,15,133,244,60,65,139,4,199,15,175,4,252,234,15,128,244,59,255,129,
- 124,253,252,234,4,239,15,133,244,63,129,124,253,194,4,239,15,133,244,63,139,
- 44,252,234,15,175,44,194,15,128,244,62,255,129,124,253,252,234,4,239,15,131,
- 244,58,65,129,124,253,199,4,239,15,131,244,58,252,242,15,16,4,252,234,252,
- 242,65,15,94,4,199,255,129,124,253,252,234,4,239,15,131,244,60,65,129,124,
- 253,199,4,239,15,131,244,60,252,242,65,15,16,4,199,252,242,15,94,4,252,234,
- 255,129,124,253,252,234,4,239,15,131,244,63,129,124,253,194,4,239,15,131,
- 244,63,252,242,15,16,4,252,234,252,242,15,94,4,194,255,252,242,15,17,4,202,
- 139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,
- 129,124,253,252,234,4,239,15,131,244,58,65,129,124,253,199,4,239,15,131,244,
- 58,252,242,15,16,4,252,234,252,242,65,15,16,12,199,255,129,124,253,252,234,
- 4,239,15,131,244,60,65,129,124,253,199,4,239,15,131,244,60,252,242,65,15,
- 16,4,199,252,242,15,16,12,252,234,255,129,124,253,252,234,4,239,15,131,244,
- 63,129,124,253,194,4,239,15,131,244,63,252,242,15,16,4,252,234,252,242,15,
- 16,12,194,255,248,166,232,244,160,252,242,15,17,4,202,139,3,15,182,204,15,
- 182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,252,233,244,166,255,
- 137,213,232,251,1,30,15,182,75,252,253,137,252,234,252,242,15,17,4,202,139,
- 3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,15,
- 182,252,236,15,182,192,139,124,36,24,137,151,233,141,52,194,137,194,41,252,
- 234,248,37,137,252,253,137,92,36,28,232,251,1,49,139,149,233,133,192,15,133,
- 244,51,15,182,107,252,255,15,182,75,252,253,72,139,4,252,234,72,137,4,202,
- 139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,
- 72,252,247,208,65,139,4,135,199,68,202,4,237,137,4,202,139,3,15,182,204,15,
- 182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,15,191,192,199,68,
- 202,4,237,137,4,202,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,
- 255,36,252,238,255,252,242,65,15,16,4,199,252,242,15,17,4,202,139,3,15,182,
- 204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,72,252,247,
- 208,137,68,202,4,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,
- 255,36,252,238,255,141,76,202,12,141,68,194,4,189,237,137,105,252,248,248,
- 1,137,41,131,193,8,57,193,15,134,244,1,139,3,15,182,204,15,182,232,131,195,
- 4,193,232,16,65,252,255,36,252,238,255,139,106,252,248,139,172,253,133,233,
- 139,173,233,72,139,69,0,72,137,4,202,139,3,15,182,204,15,182,232,131,195,
- 4,193,232,16,65,252,255,36,252,238,255,139,106,252,248,139,172,253,141,233,
- 128,189,233,0,139,173,233,139,12,194,139,68,194,4,137,77,0,137,69,4,15,132,
- 244,247,252,246,133,233,235,15,133,244,248,248,1,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,129,232,239,129,252,
- 248,239,15,134,244,1,252,246,129,233,235,15,132,244,1,137,252,238,137,213,
- 65,141,190,233,255,232,251,1,50,137,252,234,252,233,244,1,255,72,252,247,
- 208,139,106,252,248,139,172,253,141,233,65,139,12,135,139,133,233,137,8,199,
- 64,4,237,252,246,133,233,235,15,133,244,248,248,1,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,248,2,252,246,129,233,235,
- 15,132,244,1,128,189,233,0,15,132,244,1,137,213,137,198,65,141,190,233,232,
- 251,1,50,137,252,234,252,233,244,1,255,139,106,252,248,252,242,65,15,16,4,
- 199,139,172,253,141,233,139,141,233,252,242,15,17,1,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,255,72,252,247,208,139,106,
- 252,248,139,172,253,141,233,139,141,233,137,65,4,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,255,141,156,253,131,233,139,
- 108,36,24,131,189,233,0,15,132,244,247,137,149,233,141,52,202,137,252,239,
- 232,251,1,51,139,149,233,248,1,139,3,15,182,204,15,182,232,131,195,4,193,
- 232,16,65,252,255,36,252,238,255,72,252,247,208,139,108,36,24,137,149,233,
- 139,82,252,248,65,139,52,135,137,252,239,137,92,36,28,232,251,1,52,139,149,
- 233,15,182,75,252,253,137,4,202,199,68,202,4,237,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,255,139,108,36,24,137,149,
- 233,65,139,142,233,65,59,142,233,137,92,36,28,15,131,244,251,248,1,137,194,
- 37,252,255,7,0,0,193,252,234,11,61,252,255,7,0,0,15,132,244,249,248,2,137,
- 252,239,137,198,232,251,1,53,139,149,233,15,182,75,252,253,137,4,202,199,
- 68,202,4,237,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,
- 36,252,238,248,3,184,1,8,0,0,252,233,244,2,248,5,137,252,239,232,251,1,54,
- 15,183,67,252,254,252,233,244,1,255,72,252,247,208,139,108,36,24,65,139,142,
- 233,137,92,36,28,65,59,142,233,137,149,233,15,131,244,249,248,2,65,139,52,
- 135,137,252,239,232,251,1,55,139,149,233,15,182,75,252,253,137,4,202,199,
- 68,202,4,237,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,
- 36,252,238,248,3,137,252,239,232,251,1,54,15,183,67,252,254,72,252,247,208,
- 252,233,244,2,255,72,252,247,208,139,106,252,248,139,173,233,65,139,4,135,
- 252,233,244,167,255,72,252,247,208,139,106,252,248,139,173,233,65,139,4,135,
- 252,233,244,168,255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,
- 133,244,40,139,44,252,234,129,124,253,194,4,239,15,133,244,251,139,4,194,
- 59,133,233,15,131,244,40,193,224,3,3,133,233,129,120,253,4,239,15,132,244,
- 248,72,139,40,72,137,44,202,248,1,139,3,15,182,204,15,182,232,131,195,4,193,
- 232,16,65,252,255,36,252,238,248,2,131,189,233,0,15,132,244,249,139,141,233,
- 252,246,129,233,235,255,15,132,244,40,15,182,75,252,253,248,3,199,68,202,
- 4,237,252,233,244,1,248,5,129,124,253,194,4,239,15,133,244,40,139,4,194,252,
- 233,244,167,255,15,182,252,236,15,182,192,72,252,247,208,65,139,4,135,129,
- 124,253,252,234,4,239,15,133,244,38,139,44,252,234,248,167,139,141,233,35,
- 136,233,105,201,239,3,141,233,248,1,129,185,233,239,15,133,244,250,57,129,
- 233,15,133,244,250,129,121,253,4,239,15,132,244,251,15,182,67,252,253,72,
- 139,41,72,137,44,194,248,2,255,139,3,15,182,204,15,182,232,131,195,4,193,
- 232,16,65,252,255,36,252,238,248,3,15,182,67,252,253,199,68,194,4,237,252,
- 233,244,2,248,4,139,137,233,133,201,15,133,244,1,248,5,139,141,233,133,201,
- 15,132,244,3,252,246,129,233,235,15,133,244,3,252,233,244,38,255,15,182,252,
- 236,15,182,192,129,124,253,252,234,4,239,15,133,244,39,139,44,252,234,59,
- 133,233,15,131,244,39,193,224,3,3,133,233,129,120,253,4,239,15,132,244,248,
- 72,139,40,72,137,44,202,248,1,139,3,15,182,204,15,182,232,131,195,4,193,232,
- 16,65,252,255,36,252,238,248,2,131,189,233,0,15,132,244,249,139,141,233,252,
- 246,129,233,235,15,132,244,39,255,15,182,75,252,253,248,3,199,68,202,4,237,
- 252,233,244,1,255,15,182,252,236,15,182,192,139,44,252,234,139,4,194,59,133,
- 233,15,131,244,41,193,224,3,3,133,233,248,42,72,139,40,72,137,44,202,248,
- 43,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,
- 255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,46,139,
- 44,252,234,129,124,253,194,4,239,15,133,244,251,139,4,194,59,133,233,15,131,
- 244,46,193,224,3,3,133,233,129,120,253,4,239,15,132,244,249,248,1,252,246,
- 133,233,235,15,133,244,253,248,2,72,139,44,202,72,137,40,139,3,15,182,204,
- 15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,3,255,131,189,233,
- 0,15,132,244,1,139,141,233,252,246,129,233,235,15,132,244,46,15,182,75,252,
- 253,252,233,244,1,248,5,129,124,253,194,4,239,15,133,244,46,139,4,194,252,
- 233,244,168,248,7,128,165,233,235,65,139,142,233,255,65,137,174,233,137,141,
- 233,15,182,75,252,253,252,233,244,2,255,15,182,252,236,15,182,192,72,252,
- 247,208,65,139,4,135,129,124,253,252,234,4,239,15,133,244,44,139,44,252,234,
- 248,168,139,141,233,35,136,233,105,201,239,198,133,233,0,3,141,233,248,1,
- 129,185,233,239,15,133,244,251,57,129,233,15,133,244,251,129,121,253,4,239,
- 15,132,244,250,248,2,255,252,246,133,233,235,15,133,244,253,248,3,15,182,
- 67,252,253,72,139,44,194,72,137,41,139,3,15,182,204,15,182,232,131,195,4,
- 193,232,16,65,252,255,36,252,238,248,4,131,189,233,0,15,132,244,2,137,12,
- 36,139,141,233,252,246,129,233,235,15,132,244,44,139,12,36,252,233,244,2,
- 248,5,139,137,233,133,201,15,133,244,1,255,139,141,233,133,201,15,132,244,
- 252,252,246,129,233,235,15,132,244,44,248,6,137,4,36,199,68,36,4,237,137,
- 108,36,8,139,124,36,24,137,151,233,72,141,20,36,137,252,238,137,252,253,137,
- 92,36,28,232,251,1,56,139,149,233,139,108,36,8,137,193,252,233,244,2,248,
- 7,128,165,233,235,65,139,134,233,65,137,174,233,137,133,233,252,233,244,3,
- 255,15,182,252,236,15,182,192,129,124,253,252,234,4,239,15,133,244,45,139,
- 44,252,234,59,133,233,15,131,244,45,193,224,3,3,133,233,129,120,253,4,239,
- 15,132,244,249,248,1,252,246,133,233,235,15,133,244,253,248,2,72,139,12,202,
- 72,137,8,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,
- 238,248,3,131,189,233,0,15,132,244,1,255,139,141,233,252,246,129,233,235,
- 15,132,244,45,15,182,75,252,253,252,233,244,1,248,7,128,165,233,235,65,139,
- 142,233,65,137,174,233,137,141,233,15,182,75,252,253,252,233,244,2,255,15,
- 182,252,236,15,182,192,139,44,252,234,139,4,194,252,246,133,233,235,15,133,
- 244,253,248,2,59,133,233,15,131,244,48,193,224,3,3,133,233,248,49,72,139,
- 44,202,72,137,40,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,
- 255,36,252,238,248,7,128,165,233,235,65,139,142,233,65,137,174,233,137,141,
- 233,15,182,75,252,253,252,233,244,2,255,68,137,60,36,69,139,60,199,248,1,
- 141,12,202,139,105,252,248,252,246,133,233,235,15,133,244,253,248,2,139,68,
- 36,4,131,232,1,15,132,244,250,68,1,252,248,59,133,233,15,135,244,251,68,41,
- 252,248,65,193,231,3,68,3,189,233,248,3,72,139,41,131,193,8,73,137,47,65,
- 131,199,8,131,232,1,15,133,244,3,248,4,68,139,60,36,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,248,5,139,124,36,24,137,151,
- 233,137,252,238,137,194,137,252,253,137,92,36,28,232,251,1,57,139,149,233,
- 15,182,75,252,253,252,233,244,1,248,7,255,128,165,233,235,65,139,134,233,
- 65,137,174,233,137,133,233,252,233,244,2,255,3,68,36,4,255,129,124,253,202,
- 4,239,139,44,202,15,133,244,66,141,84,202,8,137,90,252,252,139,157,233,139,
- 11,15,182,252,233,15,182,205,131,195,4,65,252,255,36,252,238,255,141,76,202,
- 8,65,137,215,139,105,252,248,129,121,253,252,252,239,15,133,244,30,248,67,
- 139,90,252,252,252,247,195,237,15,133,244,253,248,1,137,106,252,248,137,68,
- 36,4,131,232,1,15,132,244,249,248,2,72,139,41,131,193,8,73,137,47,65,131,
- 199,8,131,232,1,15,133,244,2,139,106,252,248,248,3,139,68,36,4,128,189,233,
- 1,15,135,244,251,248,4,139,157,233,139,11,15,182,252,233,15,182,205,131,195,
- 4,65,252,255,36,252,238,248,5,255,252,247,195,237,15,133,244,4,15,182,75,
- 252,253,72,252,247,209,68,139,124,202,252,248,69,139,191,233,69,139,191,233,
- 252,233,244,4,248,7,129,252,235,239,252,247,195,237,15,133,244,254,41,218,
- 65,137,215,139,90,252,252,252,233,244,1,248,8,129,195,239,252,233,244,1,255,
- 141,76,202,8,72,139,105,232,72,139,65,252,240,72,137,41,72,137,65,8,139,105,
- 224,139,65,228,137,105,252,248,137,65,252,252,129,252,248,239,184,237,15,
- 133,244,30,137,202,137,90,252,252,139,157,233,139,11,15,182,252,233,15,182,
- 205,131,195,4,65,252,255,36,252,238,255,68,137,60,36,68,137,116,36,4,139,
- 108,202,252,240,139,68,202,252,248,68,139,181,233,131,195,4,68,139,189,233,
- 248,1,68,57,252,240,15,131,244,251,65,129,124,253,199,4,239,15,132,244,250,
- 199,68,202,4,237,137,4,202,73,139,44,199,72,137,108,202,8,131,192,1,137,68,
- 202,252,248,248,2,15,183,67,252,254,141,156,253,131,233,248,3,68,139,116,
- 36,4,68,139,60,36,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,
- 255,36,252,238,248,4,131,192,1,252,233,244,1,248,5,68,41,252,240,248,6,59,
- 133,233,15,135,244,3,255,68,105,252,248,239,68,3,189,233,65,129,191,233,239,
- 15,132,244,253,70,141,116,48,1,73,139,175,233,73,139,135,233,72,137,44,202,
- 72,137,68,202,8,68,137,116,202,252,248,252,233,244,2,248,7,131,192,1,252,
- 233,244,6,255,129,124,253,202,252,236,239,15,133,244,251,139,108,202,232,
- 129,124,253,202,252,244,239,15,133,244,251,129,124,253,202,252,252,239,15,
- 133,244,251,128,189,233,235,15,133,244,251,141,156,253,131,233,199,68,202,
- 252,248,0,0,0,0,199,68,202,252,252,252,255,127,252,254,252,255,248,1,139,
- 3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,5,
- 198,67,252,252,235,141,156,253,131,233,198,3,235,252,233,244,1,255,15,182,
- 252,236,15,182,192,68,137,60,36,68,141,188,253,194,233,141,12,202,68,43,122,
- 252,252,133,252,237,15,132,244,251,141,108,252,233,252,248,65,57,215,15,131,
- 244,248,248,1,73,139,71,252,248,65,131,199,8,72,137,1,131,193,8,57,252,233,
- 15,131,244,249,65,57,215,15,130,244,1,248,2,199,65,4,237,131,193,8,57,252,
- 233,15,130,244,2,248,3,68,139,60,36,139,3,15,182,204,15,182,232,131,195,4,
- 193,232,16,65,252,255,36,252,238,248,5,199,68,36,4,1,0,0,0,137,208,68,41,
- 252,248,15,134,244,3,137,197,193,252,237,3,131,197,1,137,108,36,4,139,108,
- 36,24,1,200,59,133,233,15,135,244,253,248,6,255,73,139,71,252,248,65,131,
- 199,8,72,137,1,131,193,8,65,57,215,15,130,244,6,252,233,244,3,248,7,137,149,
- 233,137,141,233,137,92,36,28,65,41,215,139,116,36,4,131,252,238,1,137,252,
- 239,232,251,1,0,139,149,233,139,141,233,65,1,215,252,233,244,6,255,193,225,
- 3,255,248,1,139,90,252,252,137,68,36,4,252,247,195,237,15,133,244,253,255,
- 248,14,65,137,215,131,232,1,15,132,244,249,248,2,73,139,44,15,73,137,111,
- 252,248,65,131,199,8,131,232,1,15,133,244,2,248,3,139,68,36,4,15,182,107,
- 252,255,248,5,57,197,15,135,244,252,255,72,139,44,10,72,137,106,252,248,255,
- 248,5,56,67,252,255,15,135,244,252,255,15,182,75,252,253,72,252,247,209,141,
- 20,202,68,139,122,252,248,69,139,191,233,69,139,191,233,139,3,15,182,204,
- 15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,248,6,255,65,199,71,
- 252,252,237,65,131,199,8,255,199,68,194,252,244,237,255,131,192,1,252,233,
- 244,5,248,7,141,171,233,252,247,197,237,15,133,244,15,41,252,234,255,1,252,
- 233,255,137,221,209,252,237,129,229,239,102,65,129,172,253,46,233,238,15,
- 130,244,150,255,141,12,202,255,129,121,253,4,239,15,133,244,255,255,129,121,
- 253,12,239,15,133,244,68,129,121,253,20,239,15,133,244,68,139,41,131,121,
- 16,0,15,140,244,251,255,129,121,253,12,239,15,133,244,163,129,121,253,20,
- 239,15,133,244,163,255,139,105,16,133,252,237,15,136,244,251,3,41,15,128,
- 244,247,137,41,255,59,105,8,199,65,28,237,137,105,24,255,15,142,244,253,248,
- 1,248,6,141,156,253,131,233,255,141,156,253,131,233,15,183,67,252,254,15,
- 142,245,248,1,248,6,255,15,143,244,253,248,6,141,156,253,131,233,248,1,255,
- 248,7,139,3,15,182,204,15,182,232,131,195,4,193,232,16,65,252,255,36,252,
- 238,248,5,255,3,41,15,128,244,1,137,41,255,15,141,244,7,255,141,156,253,131,
- 233,15,183,67,252,254,15,141,245,255,15,140,244,7,255,252,233,244,6,248,9,
- 255,129,121,253,4,239,255,15,131,244,68,129,121,253,12,239,15,131,244,68,
- 255,129,121,253,12,239,15,131,244,163,129,121,253,20,239,15,131,244,163,255,
- 139,105,20,255,129,252,253,239,15,131,244,68,255,252,242,15,16,1,252,242,
- 15,16,73,8,255,252,242,15,88,65,16,252,242,15,17,1,133,252,237,15,136,244,
- 249,255,15,140,244,249,255,102,15,46,200,248,1,252,242,15,17,65,24,255,15,
- 131,244,7,255,141,156,253,131,233,15,183,67,252,254,15,131,245,255,15,130,
- 244,7,255,252,233,244,6,248,3,102,15,46,193,252,233,244,1,255,141,12,202,
- 139,105,4,129,252,253,239,15,132,244,247,255,137,105,252,252,139,41,137,105,
- 252,248,252,233,245,255,141,156,253,131,233,139,1,137,105,252,252,137,65,
- 252,248,255,139,108,36,24,137,149,233,137,4,36,137,218,137,198,137,252,239,
- 232,251,1,58,139,4,36,139,149,233,255,65,139,142,233,139,4,129,72,139,128,
- 233,139,108,36,24,65,137,150,233,65,137,174,233,76,137,36,36,76,137,108,36,
- 8,72,131,252,236,16,252,255,224,255,141,156,253,131,233,139,3,15,182,204,
- 15,182,232,131,195,4,193,232,16,65,252,255,36,252,238,255,137,221,209,252,
- 237,129,229,239,102,65,129,172,253,46,233,238,15,130,244,152,255,68,139,187,
- 233,139,108,36,24,141,12,202,59,141,233,15,135,244,25,15,182,139,233,57,200,
- 15,134,244,249,248,2,255,15,183,67,252,254,252,233,245,255,248,3,199,68,194,
- 252,252,237,131,192,1,57,200,15,134,244,3,252,233,244,2,255,141,44,197,237,
- 141,4,194,68,139,122,252,248,137,104,252,252,68,137,120,252,248,139,108,36,
- 24,141,12,200,59,141,233,15,135,244,24,137,209,137,194,15,182,171,233,133,
- 252,237,15,132,244,248,248,1,131,193,8,57,209,15,131,244,249,68,139,121,252,
- 248,68,137,56,68,139,121,252,252,68,137,120,4,131,192,8,199,65,252,252,237,
- 131,252,237,1,15,133,244,1,248,2,255,68,139,187,233,139,3,15,182,204,15,182,
- 232,131,195,4,193,232,16,65,252,255,36,252,238,255,248,3,199,64,4,237,131,
- 192,8,131,252,237,1,15,133,244,3,252,233,244,2,255,139,106,252,248,76,139,
- 189,233,139,108,36,24,141,68,194,252,248,137,149,233,141,136,233,59,141,233,
- 137,133,233,255,137,252,239,255,76,137,252,254,137,252,239,255,15,135,244,
- 23,65,199,134,233,237,255,65,252,255,215,255,65,252,255,150,233,255,139,149,
- 233,65,137,174,233,65,199,134,233,237,141,12,194,252,247,217,3,141,233,139,
- 90,252,252,252,233,244,12,255,254,0
- };
- #line 13 "vm_x86.dasc"
- //|.globals GLOB_
- enum {
- GLOB_vm_returnp,
- GLOB_cont_dispatch,
- GLOB_vm_returnc,
- GLOB_vm_unwind_yield,
- GLOB_BC_RET_Z,
- GLOB_vm_return,
- GLOB_vm_leave_cp,
- GLOB_vm_leave_unw,
- GLOB_vm_unwind_c_eh,
- GLOB_vm_unwind_c,
- GLOB_vm_unwind_rethrow,
- GLOB_vm_unwind_ff,
- GLOB_vm_unwind_ff_eh,
- GLOB_vm_growstack_c,
- GLOB_vm_growstack_v,
- GLOB_vm_growstack_f,
- GLOB_vm_resume,
- GLOB_vm_pcall,
- GLOB_vm_call,
- GLOB_vm_call_dispatch,
- GLOB_vmeta_call,
- GLOB_vm_call_dispatch_f,
- GLOB_vm_cpcall,
- GLOB_cont_ffi_callback,
- GLOB_vm_call_tail,
- GLOB_cont_cat,
- GLOB_cont_ra,
- GLOB_BC_CAT_Z,
- GLOB_vmeta_tgets,
- GLOB_vmeta_tgetb,
- GLOB_vmeta_tgetv,
- GLOB_vmeta_tgetr,
- GLOB_BC_TGETR_Z,
- GLOB_BC_TGETR2_Z,
- GLOB_vmeta_tsets,
- GLOB_vmeta_tsetb,
- GLOB_vmeta_tsetv,
- GLOB_cont_nop,
- GLOB_vmeta_tsetr,
- GLOB_BC_TSETR_Z,
- GLOB_vmeta_comp,
- GLOB_vmeta_binop,
- GLOB_cont_condt,
- GLOB_cont_condf,
- GLOB_vmeta_equal,
- GLOB_vmeta_equal_cd,
- GLOB_vmeta_istype,
- GLOB_vmeta_arith_vno,
- GLOB_vmeta_arith_vn,
- GLOB_vmeta_arith_nvo,
- GLOB_vmeta_arith_nv,
- GLOB_vmeta_unm,
- GLOB_vmeta_arith_vvo,
- GLOB_vmeta_arith_vv,
- GLOB_vmeta_len,
- GLOB_BC_LEN_Z,
- GLOB_vmeta_call_ra,
- GLOB_BC_CALLT_Z,
- GLOB_vmeta_for,
- GLOB_ff_assert,
- GLOB_fff_fallback,
- GLOB_fff_res_,
- GLOB_ff_type,
- GLOB_fff_res1,
- GLOB_ff_getmetatable,
- GLOB_ff_setmetatable,
- GLOB_ff_rawget,
- GLOB_ff_tonumber,
- GLOB_fff_resi,
- GLOB_fff_resxmm0,
- GLOB_ff_tostring,
- GLOB_fff_gcstep,
- GLOB_ff_next,
- GLOB_fff_res2,
- GLOB_fff_res,
- GLOB_ff_pairs,
- GLOB_ff_ipairs_aux,
- GLOB_fff_res0,
- GLOB_ff_ipairs,
- GLOB_ff_pcall,
- GLOB_ff_xpcall,
- GLOB_ff_coroutine_resume,
- GLOB_ff_coroutine_wrap_aux,
- GLOB_ff_coroutine_yield,
- GLOB_fff_resn,
- GLOB_ff_math_abs,
- GLOB_fff_resbit,
- GLOB_ff_math_floor,
- GLOB_vm_floor_sse,
- GLOB_ff_math_ceil,
- GLOB_vm_ceil_sse,
- GLOB_ff_math_sqrt,
- GLOB_ff_math_log,
- GLOB_ff_math_log10,
- GLOB_ff_math_exp,
- GLOB_ff_math_sin,
- GLOB_ff_math_cos,
- GLOB_ff_math_tan,
- GLOB_ff_math_asin,
- GLOB_ff_math_acos,
- GLOB_ff_math_atan,
- GLOB_ff_math_sinh,
- GLOB_ff_math_cosh,
- GLOB_ff_math_tanh,
- GLOB_ff_math_pow,
- GLOB_ff_math_atan2,
- GLOB_ff_math_fmod,
- GLOB_ff_math_ldexp,
- GLOB_ff_math_frexp,
- GLOB_ff_math_modf,
- GLOB_vm_trunc_sse,
- GLOB_ff_math_min,
- GLOB_ff_math_max,
- GLOB_ff_string_byte,
- GLOB_ff_string_char,
- GLOB_fff_newstr,
- GLOB_fff_resstr,
- GLOB_ff_string_sub,
- GLOB_fff_emptystr,
- GLOB_ff_string_reverse,
- GLOB_ff_string_lower,
- GLOB_ff_string_upper,
- GLOB_ff_bit_tobit,
- GLOB_ff_bit_band,
- GLOB_fff_fallback_bit_op,
- GLOB_ff_bit_bor,
- GLOB_ff_bit_bxor,
- GLOB_ff_bit_bswap,
- GLOB_ff_bit_bnot,
- GLOB_ff_bit_lshift,
- GLOB_ff_bit_rshift,
- GLOB_ff_bit_arshift,
- GLOB_ff_bit_rol,
- GLOB_ff_bit_ror,
- GLOB_fff_fallback_2,
- GLOB_fff_fallback_1,
- GLOB_vm_record,
- GLOB_vm_rethook,
- GLOB_vm_inshook,
- GLOB_cont_hook,
- GLOB_vm_hotloop,
- GLOB_vm_callhook,
- GLOB_vm_hotcall,
- GLOB_cont_stitch,
- GLOB_vm_profhook,
- GLOB_vm_exit_handler,
- GLOB_vm_exit_interp,
- GLOB_vm_floor,
- GLOB_vm_ceil,
- GLOB_vm_trunc,
- GLOB_vm_mod,
- GLOB_vm_powi_sse,
- GLOB_vm_cpuid,
- GLOB_assert_bad_for_arg_type,
- GLOB_vm_ffi_callback,
- GLOB_vm_ffi_call,
- GLOB_BC_MODVN_Z,
- GLOB_BC_TGETS_Z,
- GLOB_BC_TSETS_Z,
- GLOB__MAX
- };
- #line 14 "vm_x86.dasc"
- //|.globalnames globnames
- static const char *const globnames[] = {
- "vm_returnp",
- "cont_dispatch",
- "vm_returnc",
- "vm_unwind_yield",
- "BC_RET_Z",
- "vm_return",
- "vm_leave_cp",
- "vm_leave_unw",
- "vm_unwind_c_eh",
- "vm_unwind_c@8",
- "vm_unwind_rethrow",
- "vm_unwind_ff@4",
- "vm_unwind_ff_eh",
- "vm_growstack_c",
- "vm_growstack_v",
- "vm_growstack_f",
- "vm_resume",
- "vm_pcall",
- "vm_call",
- "vm_call_dispatch",
- "vmeta_call",
- "vm_call_dispatch_f",
- "vm_cpcall",
- "cont_ffi_callback",
- "vm_call_tail",
- "cont_cat",
- "cont_ra",
- "BC_CAT_Z",
- "vmeta_tgets",
- "vmeta_tgetb",
- "vmeta_tgetv",
- "vmeta_tgetr",
- "BC_TGETR_Z",
- "BC_TGETR2_Z",
- "vmeta_tsets",
- "vmeta_tsetb",
- "vmeta_tsetv",
- "cont_nop",
- "vmeta_tsetr",
- "BC_TSETR_Z",
- "vmeta_comp",
- "vmeta_binop",
- "cont_condt",
- "cont_condf",
- "vmeta_equal",
- "vmeta_equal_cd",
- "vmeta_istype",
- "vmeta_arith_vno",
- "vmeta_arith_vn",
- "vmeta_arith_nvo",
- "vmeta_arith_nv",
- "vmeta_unm",
- "vmeta_arith_vvo",
- "vmeta_arith_vv",
- "vmeta_len",
- "BC_LEN_Z",
- "vmeta_call_ra",
- "BC_CALLT_Z",
- "vmeta_for",
- "ff_assert",
- "fff_fallback",
- "fff_res_",
- "ff_type",
- "fff_res1",
- "ff_getmetatable",
- "ff_setmetatable",
- "ff_rawget",
- "ff_tonumber",
- "fff_resi",
- "fff_resxmm0",
- "ff_tostring",
- "fff_gcstep",
- "ff_next",
- "fff_res2",
- "fff_res",
- "ff_pairs",
- "ff_ipairs_aux",
- "fff_res0",
- "ff_ipairs",
- "ff_pcall",
- "ff_xpcall",
- "ff_coroutine_resume",
- "ff_coroutine_wrap_aux",
- "ff_coroutine_yield",
- "fff_resn",
- "ff_math_abs",
- "fff_resbit",
- "ff_math_floor",
- "vm_floor_sse",
- "ff_math_ceil",
- "vm_ceil_sse",
- "ff_math_sqrt",
- "ff_math_log",
- "ff_math_log10",
- "ff_math_exp",
- "ff_math_sin",
- "ff_math_cos",
- "ff_math_tan",
- "ff_math_asin",
- "ff_math_acos",
- "ff_math_atan",
- "ff_math_sinh",
- "ff_math_cosh",
- "ff_math_tanh",
- "ff_math_pow",
- "ff_math_atan2",
- "ff_math_fmod",
- "ff_math_ldexp",
- "ff_math_frexp",
- "ff_math_modf",
- "vm_trunc_sse",
- "ff_math_min",
- "ff_math_max",
- "ff_string_byte",
- "ff_string_char",
- "fff_newstr",
- "fff_resstr",
- "ff_string_sub",
- "fff_emptystr",
- "ff_string_reverse",
- "ff_string_lower",
- "ff_string_upper",
- "ff_bit_tobit",
- "ff_bit_band",
- "fff_fallback_bit_op",
- "ff_bit_bor",
- "ff_bit_bxor",
- "ff_bit_bswap",
- "ff_bit_bnot",
- "ff_bit_lshift",
- "ff_bit_rshift",
- "ff_bit_arshift",
- "ff_bit_rol",
- "ff_bit_ror",
- "fff_fallback_2",
- "fff_fallback_1",
- "vm_record",
- "vm_rethook",
- "vm_inshook",
- "cont_hook",
- "vm_hotloop",
- "vm_callhook",
- "vm_hotcall",
- "cont_stitch",
- "vm_profhook",
- "vm_exit_handler",
- "vm_exit_interp",
- "vm_floor",
- "vm_ceil",
- "vm_trunc",
- "vm_mod",
- "vm_powi_sse",
- "vm_cpuid",
- "assert_bad_for_arg_type",
- "vm_ffi_callback",
- "vm_ffi_call@4",
- "BC_MODVN_Z",
- "BC_TGETS_Z",
- "BC_TSETS_Z",
- (const char *)0
- };
- #line 15 "vm_x86.dasc"
- //|.externnames extnames
- static const char *const extnames[] = {
- "lj_state_growstack@8",
- "lj_err_throw@8",
- "lj_meta_tget",
- "lj_tab_getinth@8",
- "lj_meta_tset",
- "lj_tab_setinth",
- "lj_meta_comp",
- "lj_meta_equal",
- "lj_meta_equal_cd@8",
- "lj_meta_istype",
- "lj_meta_arith",
- "lj_meta_len@8",
- "lj_meta_call",
- "lj_meta_for@8",
- "lj_tab_get",
- "lj_strfmt_number@8",
- "lj_tab_next",
- "lj_ffh_coroutine_wrap_err@8",
- "log",
- "log10",
- "exp",
- "sin",
- "cos",
- "tan",
- "asin",
- "acos",
- "atan",
- "sinh",
- "cosh",
- "tanh",
- "pow",
- "atan2",
- "fmod",
- "lj_str_new",
- "lj_buf_putstr_reverse@8",
- "lj_buf_tostr@4",
- "lj_buf_putstr_lower@8",
- "lj_buf_putstr_upper@8",
- "lj_gc_step@4",
- "lj_dispatch_ins@8",
- "lj_trace_hot@8",
- "lj_dispatch_call@8",
- "lj_dispatch_stitch@8",
- "lj_dispatch_profile@8",
- "lj_trace_exit@8",
- "lj_log_trace_direct_exit@8",
- "lj_ccallback_enter@8",
- "lj_ccallback_leave@8",
- "lj_tab_len@4",
- "lj_meta_cat",
- "lj_gc_barrieruv@8",
- "lj_func_closeuv@8",
- "lj_func_newL_gc",
- "lj_tab_new",
- "lj_gc_step_fixtop@4",
- "lj_tab_dup@8",
- "lj_tab_newkey",
- "lj_tab_reasize",
- "lj_log_trace_entry@8",
- (const char *)0
- };
- #line 16 "vm_x86.dasc"
- //|
- //|//-----------------------------------------------------------------------
- //|
- //|.if P64
- //|.define X64, 1
- //|.if WIN
- //|.define X64WIN, 1
- //|.endif
- //|.endif
- //|
- //|// Fixed register assignments for the interpreter.
- //|// This is very fragile and has many dependencies. Caveat emptor.
- //|.define BASE, edx // Not C callee-save, refetched anyway.
- //|.if not X64
- //|.define KBASE, edi // Must be C callee-save.
- //|.define KBASEa, KBASE
- //|.define PC, esi // Must be C callee-save.
- //|.define PCa, PC
- //|.define DISPATCH, ebx // Must be C callee-save.
- //|.elif X64WIN
- //|.define KBASE, edi // Must be C callee-save.
- //|.define KBASEa, rdi
- //|.define PC, esi // Must be C callee-save.
- //|.define PCa, rsi
- //|.define DISPATCH, ebx // Must be C callee-save.
- //|.else
- //|.define KBASE, r15d // Must be C callee-save.
- //|.define KBASEa, r15
- //|.define PC, ebx // Must be C callee-save.
- //|.define PCa, rbx
- //|.define DISPATCH, r14d // Must be C callee-save.
- //|.endif
- //|
- //|.define RA, ecx
- //|.define RAH, ch
- //|.define RAL, cl
- //|.define RB, ebp // Must be ebp (C callee-save).
- //|.define RC, eax // Must be eax.
- //|.define RCW, ax
- //|.define RCH, ah
- //|.define RCL, al
- //|.define OP, RB
- //|.define RD, RC
- //|.define RDW, RCW
- //|.define RDL, RCL
- //|.if X64
- //|.define RAa, rcx
- //|.define RBa, rbp
- //|.define RCa, rax
- //|.define RDa, rax
- //|.else
- //|.define RAa, RA
- //|.define RBa, RB
- //|.define RCa, RC
- //|.define RDa, RD
- //|.endif
- //|
- //|.if not X64
- //|.define FCARG1, ecx // x86 fastcall arguments.
- //|.define FCARG2, edx
- //|.elif X64WIN
- //|.define CARG1, rcx // x64/WIN64 C call arguments.
- //|.define CARG2, rdx
- //|.define CARG3, r8
- //|.define CARG4, r9
- //|.define CARG1d, ecx
- //|.define CARG2d, edx
- //|.define CARG3d, r8d
- //|.define CARG4d, r9d
- //|.define FCARG1, CARG1d // Upwards compatible to x86 fastcall.
- //|.define FCARG2, CARG2d
- //|.else
- //|.define CARG1, rdi // x64/POSIX C call arguments.
- //|.define CARG2, rsi
- //|.define CARG3, rdx
- //|.define CARG4, rcx
- //|.define CARG5, r8
- //|.define CARG6, r9
- //|.define CARG1d, edi
- //|.define CARG2d, esi
- //|.define CARG3d, edx
- //|.define CARG4d, ecx
- //|.define CARG5d, r8d
- //|.define CARG6d, r9d
- //|.define FCARG1, CARG1d // Simulate x86 fastcall.
- //|.define FCARG2, CARG2d
- //|.endif
- //|
- //|// Type definitions. Some of these are only used for documentation.
- //|.type L, lua_State
- #define Dt1(_V) (int)(ptrdiff_t)&(((lua_State *)0)_V)
- #line 106 "vm_x86.dasc"
- //|.type GL, global_State
- #define Dt2(_V) (int)(ptrdiff_t)&(((global_State *)0)_V)
- #line 107 "vm_x86.dasc"
- //|.type TVALUE, TValue
- #define Dt3(_V) (int)(ptrdiff_t)&(((TValue *)0)_V)
- #line 108 "vm_x86.dasc"
- //|.type GCOBJ, GCobj
- #define Dt4(_V) (int)(ptrdiff_t)&(((GCobj *)0)_V)
- #line 109 "vm_x86.dasc"
- //|.type STR, GCstr
- #define Dt5(_V) (int)(ptrdiff_t)&(((GCstr *)0)_V)
- #line 110 "vm_x86.dasc"
- //|.type TAB, GCtab
- #define Dt6(_V) (int)(ptrdiff_t)&(((GCtab *)0)_V)
- #line 111 "vm_x86.dasc"
- //|.type LFUNC, GCfuncL
- #define Dt7(_V) (int)(ptrdiff_t)&(((GCfuncL *)0)_V)
- #line 112 "vm_x86.dasc"
- //|.type CFUNC, GCfuncC
- #define Dt8(_V) (int)(ptrdiff_t)&(((GCfuncC *)0)_V)
- #line 113 "vm_x86.dasc"
- //|.type PROTO, GCproto
- #define Dt9(_V) (int)(ptrdiff_t)&(((GCproto *)0)_V)
- #line 114 "vm_x86.dasc"
- //|.type UPVAL, GCupval
- #define DtA(_V) (int)(ptrdiff_t)&(((GCupval *)0)_V)
- #line 115 "vm_x86.dasc"
- //|.type NODE, Node
- #define DtB(_V) (int)(ptrdiff_t)&(((Node *)0)_V)
- #line 116 "vm_x86.dasc"
- //|.type NARGS, int
- #define DtC(_V) (int)(ptrdiff_t)&(((int *)0)_V)
- #line 117 "vm_x86.dasc"
- //|.type TRACE, GCtrace
- #define DtD(_V) (int)(ptrdiff_t)&(((GCtrace *)0)_V)
- #line 118 "vm_x86.dasc"
- //|.type SBUF, SBuf
- #define DtE(_V) (int)(ptrdiff_t)&(((SBuf *)0)_V)
- #line 119 "vm_x86.dasc"
- //|
- //|// Stack layout while in interpreter. Must match with lj_frame.h.
- //|//-----------------------------------------------------------------------
- //|.if not X64 // x86 stack layout.
- //|
- //|.define CFRAME_SPACE, aword*7 // Delta for esp (see <--).
- //|.macro saveregs_
- //| push edi; push esi; push ebx
- //| sub esp, CFRAME_SPACE
- //|.endmacro
- //|.macro saveregs
- //| push ebp; saveregs_
- //|.endmacro
- //|.macro restoreregs
- //| add esp, CFRAME_SPACE
- //| pop ebx; pop esi; pop edi; pop ebp
- //|.endmacro
- //|
- //|.define SAVE_ERRF, aword [esp+aword*15] // vm_pcall/vm_cpcall only.
- //|.define SAVE_NRES, aword [esp+aword*14]
- //|.define SAVE_CFRAME, aword [esp+aword*13]
- //|.define SAVE_L, aword [esp+aword*12]
- //|//----- 16 byte aligned, ^^^ arguments from C caller
- //|.define SAVE_RET, aword [esp+aword*11] //<-- esp entering interpreter.
- //|.define SAVE_R4, aword [esp+aword*10]
- //|.define SAVE_R3, aword [esp+aword*9]
- //|.define SAVE_R2, aword [esp+aword*8]
- //|//----- 16 byte aligned
- //|.define SAVE_R1, aword [esp+aword*7] //<-- esp after register saves.
- //|.define SAVE_PC, aword [esp+aword*6]
- //|.define TMP2, aword [esp+aword*5]
- //|.define TMP1, aword [esp+aword*4]
- //|//----- 16 byte aligned
- //|.define ARG4, aword [esp+aword*3]
- //|.define ARG3, aword [esp+aword*2]
- //|.define ARG2, aword [esp+aword*1]
- //|.define ARG1, aword [esp] //<-- esp while in interpreter.
- //|//----- 16 byte aligned, ^^^ arguments for C callee
- //|
- //|// FPARGx overlaps ARGx and ARG(x+1) on x86.
- //|.define FPARG3, qword [esp+qword*1]
- //|.define FPARG1, qword [esp]
- //|// TMPQ overlaps TMP1/TMP2. ARG5/MULTRES overlap TMP1/TMP2 (and TMPQ).
- //|.define TMPQ, qword [esp+aword*4]
- //|.define TMP3, ARG4
- //|.define ARG5, TMP1
- //|.define TMPa, TMP1
- //|.define MULTRES, TMP2
- //|
- //|// Arguments for vm_call and vm_pcall.
- //|.define INARG_BASE, SAVE_CFRAME // Overwritten by SAVE_CFRAME!
- //|
- //|// Arguments for vm_cpcall.
- //|.define INARG_CP_CALL, SAVE_ERRF
- //|.define INARG_CP_UD, SAVE_NRES
- //|.define INARG_CP_FUNC, SAVE_CFRAME
- //|
- //|//-----------------------------------------------------------------------
- //|.elif X64WIN // x64/Windows stack layout
- //|
- //|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--).
- //|.macro saveregs_
- //| push rdi; push rsi; push rbx
- //| sub rsp, CFRAME_SPACE
- //|.endmacro
- //|.macro saveregs
- //| push rbp; saveregs_
- //|.endmacro
- //|.macro restoreregs
- //| add rsp, CFRAME_SPACE
- //| pop rbx; pop rsi; pop rdi; pop rbp
- //|.endmacro
- //|
- //|.define SAVE_CFRAME, aword [rsp+aword*13]
- //|.define SAVE_PC, dword [rsp+dword*25]
- //|.define SAVE_L, dword [rsp+dword*24]
- //|.define SAVE_ERRF, dword [rsp+dword*23]
- //|.define SAVE_NRES, dword [rsp+dword*22]
- //|.define TMP2, dword [rsp+dword*21]
- //|.define TMP1, dword [rsp+dword*20]
- //|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by interpreter
- //|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter.
- //|.define SAVE_R4, aword [rsp+aword*8]
- //|.define SAVE_R3, aword [rsp+aword*7]
- //|.define SAVE_R2, aword [rsp+aword*6]
- //|.define SAVE_R1, aword [rsp+aword*5] //<-- rsp after register saves.
- //|.define ARG5, aword [rsp+aword*4]
- //|.define CSAVE_4, aword [rsp+aword*3]
- //|.define CSAVE_3, aword [rsp+aword*2]
- //|.define CSAVE_2, aword [rsp+aword*1]
- //|.define CSAVE_1, aword [rsp] //<-- rsp while in interpreter.
- //|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by callee
- //|
- //|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ).
- //|.define TMPQ, qword [rsp+aword*10]
- //|.define MULTRES, TMP2
- //|.define TMPa, ARG5
- //|.define ARG5d, dword [rsp+aword*4]
- //|.define TMP3, ARG5d
- //|
- //|//-----------------------------------------------------------------------
- //|.else // x64/POSIX stack layout
- //|
- //|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--).
- //|.macro saveregs_
- //| push rbx; push r15; push r14
- //| sub rsp, CFRAME_SPACE
- //|.endmacro
- //|.macro saveregs
- //| push rbp; saveregs_
- //|.endmacro
- //|.macro restoreregs
- //| add rsp, CFRAME_SPACE
- //| pop r14; pop r15; pop rbx; pop rbp
- //|.endmacro
- //|
- //|//----- 16 byte aligned,
- //|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter.
- //|.define SAVE_R4, aword [rsp+aword*8]
- //|.define SAVE_R3, aword [rsp+aword*7]
- //|.define SAVE_R2, aword [rsp+aword*6]
- //|.define SAVE_R1, aword [rsp+aword*5] //<-- rsp after register saves.
- //|.define SAVE_CFRAME, aword [rsp+aword*4]
- //|.define SAVE_PC, dword [rsp+dword*7]
- //|.define SAVE_L, dword [rsp+dword*6]
- //|.define SAVE_ERRF, dword [rsp+dword*5]
- //|.define SAVE_NRES, dword [rsp+dword*4]
- //|.define TMPa, aword [rsp+aword*1]
- //|.define TMP2, dword [rsp+dword*1]
- //|.define TMP1, dword [rsp] //<-- rsp while in interpreter.
- //|//----- 16 byte aligned
- //|
- //|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ).
- //|.define TMPQ, qword [rsp]
- //|.define TMP3, dword [rsp+aword*1]
- //|.define MULTRES, TMP2
- //|
- //|.endif
- //|
- //|//-----------------------------------------------------------------------
- //|
- //|// Instruction headers.
- //|.macro ins_A; .endmacro
- //|.macro ins_AD; .endmacro
- //|.macro ins_AJ; .endmacro
- //|.macro ins_ABC; movzx RB, RCH; movzx RC, RCL; .endmacro
- //|.macro ins_AB_; movzx RB, RCH; .endmacro
- //|.macro ins_A_C; movzx RC, RCL; .endmacro
- //|.macro ins_AND; not RDa; .endmacro
- //|
- //|// Instruction decode+dispatch. Carefully tuned (nope, lodsd is not faster).
- //|.macro ins_NEXT
- //| mov RC, [PC]
- //| movzx RA, RCH
- //| movzx OP, RCL
- //| add PC, 4
- //| shr RC, 16
- //|.if X64
- //| jmp aword [DISPATCH+OP*8]
- //|.else
- //| jmp aword [DISPATCH+OP*4]
- //|.endif
- //|.endmacro
- //|
- //|// Instruction footer.
- //|.if 1
- //| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use.
- //| .define ins_next, ins_NEXT
- //| .define ins_next_, ins_NEXT
- //|.else
- //| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch.
- //| // Affects only certain kinds of benchmarks (and only with -j off).
- //| // Around 10%-30% slower on Core2, a lot more slower on P4.
- //| .macro ins_next
- //| jmp ->ins_next
- //| .endmacro
- //| .macro ins_next_
- //| ->ins_next:
- //| ins_NEXT
- //| .endmacro
- //|.endif
- //|
- //|// Call decode and dispatch.
- //|.macro ins_callt
- //| // BASE = new base, RB = LFUNC, RD = nargs+1, [BASE-4] = PC
- //| mov PC, LFUNC:RB->pc
- //| mov RA, [PC]
- //| movzx OP, RAL
- //| movzx RA, RAH
- //| add PC, 4
- //|.if X64
- //| jmp aword [DISPATCH+OP*8]
- //|.else
- //| jmp aword [DISPATCH+OP*4]
- //|.endif
- //|.endmacro
- //|
- //|.macro ins_call
- //| // BASE = new base, RB = LFUNC, RD = nargs+1
- //| mov [BASE-4], PC
- //| ins_callt
- //|.endmacro
- //|
- //|//-----------------------------------------------------------------------
- //|
- //|// Macros to test operand types.
- //|.macro checktp, reg, tp; cmp dword [BASE+reg*8+4], tp; .endmacro
- //|.macro checknum, reg, target; checktp reg, LJ_TISNUM; jae target; .endmacro
- //|.macro checkint, reg, target; checktp reg, LJ_TISNUM; jne target; .endmacro
- //|.macro checkstr, reg, target; checktp reg, LJ_TSTR; jne target; .endmacro
- //|.macro checktab, reg, target; checktp reg, LJ_TTAB; jne target; .endmacro
- //|
- //|// These operands must be used with movzx.
- //|.define PC_OP, byte [PC-4]
- //|.define PC_RA, byte [PC-3]
- //|.define PC_RB, byte [PC-1]
- //|.define PC_RC, byte [PC-2]
- //|.define PC_RD, word [PC-2]
- //|
- //|.macro branchPC, reg
- //| lea PC, [PC+reg*4-BCBIAS_J*4]
- //|.endmacro
- //|
- //|// Assumes DISPATCH is relative to GL.
- #define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
- #define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
- //|
- #define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto))
- //|
- //|// Decrement hashed hotcount and trigger trace recorder if zero.
- //|.macro hotloop, reg
- //| mov reg, PC
- //| shr reg, 1
- //| and reg, HOTCOUNT_PCMASK
- //| sub word [DISPATCH+reg+GG_DISP2HOT], HOTCOUNT_LOOP
- //| jb ->vm_hotloop
- //|.endmacro
- //|
- //|.macro hotcall, reg
- //| mov reg, PC
- //| shr reg, 1
- //| and reg, HOTCOUNT_PCMASK
- //| sub word [DISPATCH+reg+GG_DISP2HOT], HOTCOUNT_CALL
- //| jb ->vm_hotcall
- //|.endmacro
- //|
- //|// Set current VM state.
- //|.macro set_vmstate, st
- //| mov dword [DISPATCH+DISPATCH_GL(vmstate)], ~LJ_VMST_..st
- //|.endmacro
- //|
- //|// x87 compares.
- //|.macro fcomparepp // Compare and pop st0 >< st1.
- //| fucomip st1
- //| fpop
- //|.endmacro
- //|
- //|.macro fpop1; fstp st1; .endmacro
- //|
- //|// Synthesize SSE FP constants.
- //|.macro sseconst_abs, reg, tmp // Synthesize abs mask.
- //|.if X64
- //| mov64 tmp, U64x(7fffffff,ffffffff); movd reg, tmp
- //|.else
- //| pxor reg, reg; pcmpeqd reg, reg; psrlq reg, 1
- //|.endif
- //|.endmacro
- //|
- //|.macro sseconst_hi, reg, tmp, val // Synthesize hi-32 bit const.
- //|.if X64
- //| mov64 tmp, U64x(val,00000000); movd reg, tmp
- //|.else
- //| mov tmp, 0x .. val; movd reg, tmp; pshufd reg, reg, 0x51
- //|.endif
- //|.endmacro
- //|
- //|.macro sseconst_sign, reg, tmp // Synthesize sign mask.
- //| sseconst_hi reg, tmp, 80000000
- //|.endmacro
- //|.macro sseconst_1, reg, tmp // Synthesize 1.0.
- //| sseconst_hi reg, tmp, 3ff00000
- //|.endmacro
- //|.macro sseconst_m1, reg, tmp // Synthesize -1.0.
- //| sseconst_hi reg, tmp, bff00000
- //|.endmacro
- //|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
- //| sseconst_hi reg, tmp, 43300000
- //|.endmacro
- //|.macro sseconst_tobit, reg, tmp // Synthesize 2^52 + 2^51.
- //| sseconst_hi reg, tmp, 43380000
- //|.endmacro
- //|
- //|// Move table write barrier back. Overwrites reg.
- //|.macro barrierback, tab, reg
- //| and byte tab->marked, (uint8_t)~LJ_GC_BLACK // black2gray(tab)
- //| mov reg, [DISPATCH+DISPATCH_GL(gc.grayagain)]
- //| mov [DISPATCH+DISPATCH_GL(gc.grayagain)], tab
- //| mov tab->gclist, reg
- //|.endmacro
- //|
- //|//-----------------------------------------------------------------------
- /* Generate subroutines used by opcodes and other parts of the VM. */
- /* The .code_sub section should be last to help static branch prediction. */
- static void build_subroutines(BuildCtx *ctx)
- {
- //|.code_sub
- dasm_put(Dst, 0);
- #line 426 "vm_x86.dasc"
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Return handling ----------------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|->vm_returnp:
- //| test PC, FRAME_P
- //| jz ->cont_dispatch
- //|
- //| // Return from pcall or xpcall fast func.
- //| and PC, -8
- //| sub BASE, PC // Restore caller base.
- //| lea RAa, [RA+PC-8] // Rebase RA and prepend one result.
- //| mov PC, [BASE-4] // Fetch PC of previous frame.
- //| // Prepending may overwrite the pcall frame, so do it at the end.
- //| mov dword [BASE+RA+4], LJ_TTRUE // Prepend true to results.
- //|
- //|->vm_returnc:
- //| add RD, 1 // RD = nresults+1
- //| jz ->vm_unwind_yield
- //| mov MULTRES, RD
- //| test PC, FRAME_TYPE
- //| jz ->BC_RET_Z // Handle regular return to Lua.
- //|
- //|->vm_return:
- //| // BASE = base, RA = resultofs, RD = nresults+1 (= MULTRES), PC = return
- //| xor PC, FRAME_C
- //| test PC, FRAME_TYPE
- //| jnz ->vm_returnp
- //|
- //| // Return to C.
- //| set_vmstate C
- //| and PC, -8
- //| sub PC, BASE
- //| neg PC // Previous base = BASE - delta.
- //|
- //| sub RD, 1
- //| jz >2
- //|1: // Move results down.
- //|.if X64
- //| mov RBa, [BASE+RA]
- dasm_put(Dst, 2, FRAME_P, LJ_TTRUE, FRAME_TYPE, FRAME_C, FRAME_TYPE, DISPATCH_GL(vmstate), ~LJ_VMST_C);
- #line 467 "vm_x86.dasc"
- //| mov [BASE-8], RBa
- //|.else
- //| mov RB, [BASE+RA]
- //| mov [BASE-8], RB
- //| mov RB, [BASE+RA+4]
- //| mov [BASE-4], RB
- //|.endif
- //| add BASE, 8
- //| sub RD, 1
- //| jnz <1
- //|2:
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, PC
- //|3:
- //| mov RD, MULTRES
- //| mov RA, SAVE_NRES // RA = wanted nresults+1
- //|4:
- //| cmp RA, RD
- //| jne >6 // More/less results wanted?
- //|5:
- //| sub BASE, 8
- //| mov L:RB->top, BASE
- //|
- //|->vm_leave_cp:
- //| mov RAa, SAVE_CFRAME // Restore previous C frame.
- //| mov L:RB->cframe, RAa
- //| xor eax, eax // Ok return status for vm_pcall.
- //|
- //|->vm_leave_unw:
- //| restoreregs
- //| ret
- //|
- //|6:
- //| jb >7 // Less results wanted?
- //| // More results wanted. Check stack size and fill up results with nil.
- //| cmp BASE, L:RB->maxstack
- //| ja >8
- //| mov dword [BASE-4], LJ_TNIL
- //| add BASE, 8
- dasm_put(Dst, 92, Dt1(->base), Dt1(->top), Dt1(->cframe), Dt1(->maxstack), LJ_TNIL);
- #line 506 "vm_x86.dasc"
- //| add RD, 1
- //| jmp <4
- //|
- //|7: // Less results wanted.
- //| test RA, RA
- //| jz <5 // But check for LUA_MULTRET+1.
- //| sub RA, RD // Negative result!
- //| lea BASE, [BASE+RA*8] // Correct top.
- //| jmp <5
- //|
- //|8: // Corner case: need to grow stack for filling up results.
- //| // This can happen if:
- //| // - A C function grows the stack (a lot).
- //| // - The GC shrinks the stack in between.
- //| // - A return back from a lua_call() with (high) nresults adjustment.
- //| mov L:RB->top, BASE // Save current top held in BASE (yes).
- //| mov MULTRES, RD // Need to fill only remainder with nil.
- //| mov FCARG2, RA
- //| mov FCARG1, L:RB
- //| call extern lj_state_growstack@8 // (lua_State *L, int n)
- //| mov BASE, L:RB->top // Need the (realloced) L->top in BASE.
- //| jmp <3
- //|
- //|->vm_unwind_yield:
- //| mov al, LUA_YIELD
- //| jmp ->vm_unwind_c_eh
- //|
- //|->vm_unwind_c@8: // Unwind C stack, return from vm_pcall.
- //| // (void *cframe, int errcode)
- //|.if X64
- //| mov eax, CARG2d // Error return status for vm_pcall.
- //| mov rsp, CARG1
- //|.else
- //| mov eax, FCARG2 // Error return status for vm_pcall.
- //| mov esp, FCARG1
- //|.endif
- //|->vm_unwind_c_eh: // Landing pad for external unwinder.
- //| mov L:RB, SAVE_L
- //| mov GL:RB, L:RB->glref
- //| mov dword GL:RB->vmstate, ~LJ_VMST_C
- //| jmp ->vm_leave_unw
- dasm_put(Dst, 192, Dt1(->top), Dt1(->top), LUA_YIELD, Dt1(->glref), Dt2(->vmstate), ~LJ_VMST_C);
- #line 547 "vm_x86.dasc"
- //|
- //|->vm_unwind_rethrow:
- //|.if X64 and not X64WIN
- //| mov FCARG1, SAVE_L
- //| mov FCARG2, eax
- //| restoreregs
- //| jmp extern lj_err_throw@8 // (lua_State *L, int errcode)
- //|.endif
- //|
- //|->vm_unwind_ff@4: // Unwind C stack, return from ff pcall.
- //| // (void *cframe)
- //|.if X64
- //| and CARG1, CFRAME_RAWMASK
- //| mov rsp, CARG1
- //|.else
- //| and FCARG1, CFRAME_RAWMASK
- //| mov esp, FCARG1
- //|.endif
- //|->vm_unwind_ff_eh: // Landing pad for external unwinder.
- //| mov L:RB, SAVE_L
- //| mov RAa, -8 // Results start at BASE+RA = BASE-8.
- //| mov RD, 1+1 // Really 1+2 results, incr. later.
- //| mov BASE, L:RB->base
- //| mov DISPATCH, L:RB->glref // Setup pointer to dispatch table.
- //| add DISPATCH, GG_G2DISP
- //| mov PC, [BASE-4] // Fetch PC of previous frame.
- //| mov dword [BASE-4], LJ_TFALSE // Prepend false to error message.
- //| set_vmstate INTERP
- //| jmp ->vm_returnc // Increments RD/MULTRES and returns.
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Grow stack for calls -----------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|->vm_growstack_c: // Grow stack for C function.
- //| mov FCARG2, LUA_MINSTACK
- //| jmp >2
- //|
- //|->vm_growstack_v: // Grow stack for vararg Lua function.
- //| sub RD, 8
- dasm_put(Dst, 275, CFRAME_RAWMASK, 1+1, Dt1(->base), Dt1(->glref), GG_G2DISP, LJ_TFALSE, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, LUA_MINSTACK);
- #line 587 "vm_x86.dasc"
- //| jmp >1
- //|
- //|->vm_growstack_f: // Grow stack for fixarg Lua function.
- //| // BASE = new base, RD = nargs+1, RB = L, PC = first PC
- //| lea RD, [BASE+NARGS:RD*8-8]
- //|1:
- //| movzx RA, byte [PC-4+PC2PROTO(framesize)]
- //| add PC, 4 // Must point after first instruction.
- //| mov L:RB->base, BASE
- //| mov L:RB->top, RD
- //| mov SAVE_PC, PC
- //| mov FCARG2, RA
- //|2:
- //| // RB = L, L->base = new base, L->top = top
- //| mov FCARG1, L:RB
- //| call extern lj_state_growstack@8 // (lua_State *L, int n)
- //| mov BASE, L:RB->base
- //| mov RD, L:RB->top
- //| mov LFUNC:RB, [BASE-8]
- //| sub RD, BASE
- //| shr RD, 3
- //| add NARGS:RD, 1
- //| // BASE = new base, RB = LFUNC, RD = nargs+1
- //| ins_callt // Just retry the call.
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Entry points into the assembler VM ---------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|->vm_resume: // Setup C frame and resume thread.
- //| // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0)
- //| saveregs
- //|.if X64
- //| mov L:RB, CARG1d // Caveat: CARG1d may be RA.
- //| mov SAVE_L, CARG1d
- //| mov RA, CARG2d
- //|.else
- //| mov L:RB, SAVE_L
- //| mov RA, INARG_BASE // Caveat: overlaps SAVE_CFRAME!
- //|.endif
- //| mov PC, FRAME_CP
- //| xor RD, RD
- //| lea KBASEa, [esp+CFRAME_RESUME]
- //| mov DISPATCH, L:RB->glref // Setup pointer to dispatch table.
- //| add DISPATCH, GG_G2DISP
- //| mov SAVE_PC, RD // Any value outside of bytecode is ok.
- //| mov SAVE_CFRAME, RDa
- //|.if X64
- //| mov SAVE_NRES, RD
- //| mov SAVE_ERRF, RD
- //|.endif
- //| mov L:RB->cframe, KBASEa
- //| cmp byte L:RB->status, RDL
- //| je >2 // Initial resume (like a call).
- //|
- //| // Resume after yield (like a return).
- //| mov [DISPATCH+DISPATCH_GL(cur_L)], L:RB
- dasm_put(Dst, 371, -4+PC2PROTO(framesize), Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), Dt7(->pc), FRAME_CP, CFRAME_RESUME, Dt1(->glref), GG_G2DISP, Dt1(->cframe), Dt1(->status));
- #line 644 "vm_x86.dasc"
- //| set_vmstate INTERP
- //| mov byte L:RB->status, RDL
- //| mov BASE, L:RB->base
- //| mov RD, L:RB->top
- //| sub RD, RA
- //| shr RD, 3
- //| add RD, 1 // RD = nresults+1
- //| sub RA, BASE // RA = resultofs
- //| mov PC, [BASE-4]
- //| mov MULTRES, RD
- //| test PC, FRAME_TYPE
- //| jz ->BC_RET_Z
- //| jmp ->vm_return
- //|
- //|->vm_pcall: // Setup protected C frame and enter VM.
- //| // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef)
- //| saveregs
- //| mov PC, FRAME_CP
- //|.if X64
- //| mov SAVE_ERRF, CARG4d
- //|.endif
- //| jmp >1
- //|
- //|->vm_call: // Setup C frame and enter VM.
- //| // (lua_State *L, TValue *base, int nres1)
- //| saveregs
- //| mov PC, FRAME_C
- //|
- //|1: // Entry point for vm_pcall above (PC = ftype).
- //|.if X64
- //| mov SAVE_NRES, CARG3d
- //| mov L:RB, CARG1d // Caveat: CARG1d may be RA.
- //| mov SAVE_L, CARG1d
- //| mov RA, CARG2d
- //|.else
- //| mov L:RB, SAVE_L
- //| mov RA, INARG_BASE // Caveat: overlaps SAVE_CFRAME!
- //|.endif
- //|
- //| mov DISPATCH, L:RB->glref // Setup pointer to dispatch table.
- //| mov KBASEa, L:RB->cframe // Add our C frame to cframe chain.
- //| mov SAVE_CFRAME, KBASEa
- dasm_put(Dst, 524, DISPATCH_GL(cur_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->status), Dt1(->base), Dt1(->top), FRAME_TYPE, FRAME_CP, FRAME_C, Dt1(->glref), Dt1(->cframe));
- #line 686 "vm_x86.dasc"
- //| mov SAVE_PC, L:RB // Any value outside of bytecode is ok.
- //| add DISPATCH, GG_G2DISP
- //|.if X64
- //| mov L:RB->cframe, rsp
- //|.else
- //| mov L:RB->cframe, esp
- //|.endif
- //|
- //|2: // Entry point for vm_resume/vm_cpcall (RA = base, RB = L, PC = ftype).
- //| mov [DISPATCH+DISPATCH_GL(cur_L)], L:RB
- //| set_vmstate INTERP
- //| mov BASE, L:RB->base // BASE = old base (used in vmeta_call).
- //| add PC, RA
- //| sub PC, BASE // PC = frame delta + frame type
- //|
- //| mov RD, L:RB->top
- //| sub RD, RA
- //| shr NARGS:RD, 3
- //| add NARGS:RD, 1 // RD = nargs+1
- //|
- //|->vm_call_dispatch:
- //| mov LFUNC:RB, [RA-8]
- //| cmp dword [RA-4], LJ_TFUNC
- //| jne ->vmeta_call // Ensure KBASE defined and != BASE.
- //|
- //|->vm_call_dispatch_f:
- //| mov BASE, RA
- //| ins_call
- //| // BASE = new base, RB = func, RD = nargs+1, PC = caller PC
- //|
- //|->vm_cpcall: // Setup protected C frame, call C.
- //| // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
- //| saveregs
- //|.if X64
- //| mov L:RB, CARG1d // Caveat: CARG1d may be RA.
- //| mov SAVE_L, CARG1d
- //|.else
- //| mov L:RB, SAVE_L
- //| // Caveat: INARG_CP_* and SAVE_CFRAME/SAVE_NRES/SAVE_ERRF overlap!
- //| mov RC, INARG_CP_UD // Get args before they are overwritten.
- //| mov RA, INARG_CP_FUNC
- //| mov BASE, INARG_CP_CALL
- //|.endif
- //| mov SAVE_PC, L:RB // Any value outside of bytecode is ok.
- //|
- //| mov KBASE, L:RB->stack // Compute -savestack(L, L->top).
- //| sub KBASE, L:RB->top
- //| mov DISPATCH, L:RB->glref // Setup pointer to dispatch table.
- //| mov SAVE_ERRF, 0 // No error function.
- //| mov SAVE_NRES, KBASE // Neg. delta means cframe w/o frame.
- //| add DISPATCH, GG_G2DISP
- //| // Handler may change cframe_nres(L->cframe) or cframe_errfunc(L->cframe).
- //|
- //|.if X64
- //| mov KBASEa, L:RB->cframe // Add our C frame to cframe chain.
- //| mov SAVE_CFRAME, KBASEa
- dasm_put(Dst, 635, GG_G2DISP, Dt1(->cframe), DISPATCH_GL(cur_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top), LJ_TFUNC, Dt7(->pc), Dt1(->stack), Dt1(->top), Dt1(->glref), GG_G2DISP, Dt1(->cframe));
- #line 742 "vm_x86.dasc"
- //| mov L:RB->cframe, rsp
- //| mov [DISPATCH+DISPATCH_GL(cur_L)], L:RB
- //|
- //| call CARG4 // (lua_State *L, lua_CFunction func, void *ud)
- //|.else
- //| mov ARG3, RC // Have to copy args downwards.
- //| mov ARG2, RA
- //| mov ARG1, L:RB
- //|
- //| mov KBASE, L:RB->cframe // Add our C frame to cframe chain.
- //| mov SAVE_CFRAME, KBASE
- //| mov L:RB->cframe, esp
- //| mov [DISPATCH+DISPATCH_GL(cur_L)], L:RB
- //|
- //| call BASE // (lua_State *L, lua_CFunction func, void *ud)
- //|.endif
- //| // TValue * (new base) or NULL returned in eax (RC).
- //| test RC, RC
- //| jz ->vm_leave_cp // No base? Just remove C frame.
- //| mov RA, RC
- //| mov PC, FRAME_CP
- //| jmp <2 // Else continue with the call.
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Metamethod handling ------------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|//-- Continuation dispatch ----------------------------------------------
- //|
- //|->cont_dispatch:
- //| // BASE = meta base, RA = resultofs, RD = nresults+1 (also in MULTRES)
- //| add RA, BASE
- //| and PC, -8
- //| mov RB, BASE
- //| sub BASE, PC // Restore caller BASE.
- //| mov dword [RA+RD*8-4], LJ_TNIL // Ensure one valid arg.
- //| mov RC, RA // ... in [RC]
- //| mov PC, [RB-12] // Restore PC from [cont|PC].
- //|.if X64
- //| movsxd RAa, dword [RB-16] // May be negative on WIN64 with debug.
- //|.if FFI
- //| cmp RA, 1
- //| jbe >1
- //|.endif
- //| lea KBASEa, qword [=>0]
- //| add RAa, KBASEa
- //|.else
- //| mov RA, dword [RB-16]
- //|.if FFI
- //| cmp RA, 1
- //| jbe >1
- //|.endif
- //|.endif
- //| mov LFUNC:KBASE, [BASE-8]
- //| mov KBASE, LFUNC:KBASE->pc
- //| mov KBASE, [KBASE+PC2PROTO(k)]
- //| // BASE = base, RC = result, RB = meta base
- //| jmp RAa // Jump to continuation.
- //|
- //|.if FFI
- //|1:
- //| je ->cont_ffi_callback // cont = 1: return from FFI callback.
- //| // cont = 0: Tail call from C function.
- //| sub RB, BASE
- //| shr RB, 3
- //| lea RD, [RB-1]
- //| jmp ->vm_call_tail
- //|.endif
- //|
- //|->cont_cat: // BASE = base, RC = result, RB = mbase
- //| movzx RA, PC_RB
- dasm_put(Dst, 784, Dt1(->cframe), DISPATCH_GL(cur_L), FRAME_CP, LJ_TNIL, 0, Dt7(->pc), PC2PROTO(k));
- #line 813 "vm_x86.dasc"
- //| sub RB, 16
- //| lea RA, [BASE+RA*8]
- //| sub RA, RB
- //| je ->cont_ra
- //| neg RA
- //| shr RA, 3
- //|.if X64WIN
- //| mov CARG3d, RA
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE
- //| mov RCa, [RC]
- //| mov [RB], RCa
- //| mov CARG2d, RB
- //|.elif X64
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE
- //| mov CARG3d, RA
- //| mov RAa, [RC]
- //| mov [RB], RAa
- //| mov CARG2d, RB
- //|.else
- //| mov ARG3, RA
- //| mov RA, [RC+4]
- //| mov RC, [RC]
- //| mov [RB+4], RA
- //| mov [RB], RC
- //| mov ARG2, RB
- //|.endif
- //| jmp ->BC_CAT_Z
- //|
- //|//-- Table indexing metamethods -----------------------------------------
- //|
- //|->vmeta_tgets:
- //| mov TMP1, RC // RC = GCstr *
- //| mov TMP2, LJ_TSTR
- //| lea RCa, TMP1 // Store temp. TValue in TMP1/TMP2.
- //| cmp PC_OP, BC_GGET
- //| jne >1
- //| lea RA, [DISPATCH+DISPATCH_GL(tmptv)] // Store fn->l.env in g->tmptv.
- //| mov [RA], TAB:RB // RB = GCtab *
- //| mov dword [RA+4], LJ_TTAB
- //| mov RB, RA
- //| jmp >2
- //|
- //|->vmeta_tgetb:
- //| movzx RC, PC_RC
- //|.if DUALNUM
- //| mov TMP2, LJ_TISNUM
- //| mov TMP1, RC
- //|.else
- //| cvtsi2sd xmm0, RC
- //| movsd TMPQ, xmm0
- //|.endif
- //| lea RCa, TMPQ // Store temp. TValue in TMPQ.
- //| jmp >1
- //|
- //|->vmeta_tgetv:
- //| movzx RC, PC_RC // Reload TValue *k from RC.
- //| lea RC, [BASE+RC*8]
- //|1:
- //| movzx RB, PC_RB // Reload TValue *t from RB.
- dasm_put(Dst, 898, Dt1(->base), LJ_TSTR, BC_GGET, DISPATCH_GL(tmptv), LJ_TTAB, LJ_TISNUM);
- #line 874 "vm_x86.dasc"
- //| lea RB, [BASE+RB*8]
- //|2:
- //|.if X64
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE.
- //| mov CARG2d, RB
- //| mov CARG3, RCa // May be 64 bit ptr to stack.
- //| mov L:RB, L:CARG1d
- //|.else
- //| mov ARG2, RB
- //| mov L:RB, SAVE_L
- //| mov ARG3, RC
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k)
- //| // TValue * (finished) or NULL (metamethod) returned in eax (RC).
- //| mov BASE, L:RB->base
- //| test RC, RC
- //| jz >3
- //|->cont_ra: // BASE = base, RC = result
- //| movzx RA, PC_RA
- //|.if X64
- //| mov RBa, [RC]
- //| mov [BASE+RA*8], RBa
- //|.else
- //| mov RB, [RC+4]
- //| mov RC, [RC]
- //| mov [BASE+RA*8+4], RB
- //| mov [BASE+RA*8], RC
- //|.endif
- //| ins_next
- //|
- //|3: // Call __index metamethod.
- //| // BASE = base, L->top = new base, stack = cont/func/t/k
- //| mov RA, L:RB->top
- //| mov [RA-12], PC // [cont|PC]
- //| lea PC, [RA+FRAME_CONT]
- //| sub PC, BASE
- //| mov LFUNC:RB, [RA-8] // Guaranteed to be a function here.
- //| mov NARGS:RD, 2+1 // 2 args for func(t, k).
- //| jmp ->vm_call_dispatch_f
- //|
- //|->vmeta_tgetr:
- //| mov FCARG1, TAB:RB
- //| mov RB, BASE // Save BASE.
- //| mov FCARG2, RC // Caveat: FCARG2 == BASE
- //| call extern lj_tab_getinth@8 // (GCtab *t, int32_t key)
- //| // cTValue * or NULL returned in eax (RC).
- //| movzx RA, PC_RA
- //| mov BASE, RB // Restore BASE.
- //| test RC, RC
- //| jnz ->BC_TGETR_Z
- //| mov dword [BASE+RA*8+4], LJ_TNIL
- //| jmp ->BC_TGETR2_Z
- //|
- //|//-----------------------------------------------------------------------
- //|
- //|->vmeta_tsets:
- //| mov TMP1, RC // RC = GCstr *
- //| mov TMP2, LJ_TSTR
- //| lea RCa, TMP1 // Store temp. TValue in TMP1/TMP2.
- dasm_put(Dst, 1022, Dt1(->base), Dt1(->base), Dt1(->top), FRAME_CONT, 2+1, LJ_TNIL, LJ_TSTR);
- #line 937 "vm_x86.dasc"
- //| cmp PC_OP, BC_GSET
- //| jne >1
- //| lea RA, [DISPATCH+DISPATCH_GL(tmptv)] // Store fn->l.env in g->tmptv.
- //| mov [RA], TAB:RB // RB = GCtab *
- //| mov dword [RA+4], LJ_TTAB
- //| mov RB, RA
- //| jmp >2
- //|
- //|->vmeta_tsetb:
- //| movzx RC, PC_RC
- //|.if DUALNUM
- //| mov TMP2, LJ_TISNUM
- //| mov TMP1, RC
- //|.else
- //| cvtsi2sd xmm0, RC
- //| movsd TMPQ, xmm0
- //|.endif
- //| lea RCa, TMPQ // Store temp. TValue in TMPQ.
- //| jmp >1
- //|
- //|->vmeta_tsetv:
- //| movzx RC, PC_RC // Reload TValue *k from RC.
- //| lea RC, [BASE+RC*8]
- //|1:
- //| movzx RB, PC_RB // Reload TValue *t from RB.
- //| lea RB, [BASE+RB*8]
- //|2:
- //|.if X64
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE.
- //| mov CARG2d, RB
- //| mov CARG3, RCa // May be 64 bit ptr to stack.
- //| mov L:RB, L:CARG1d
- //|.else
- //| mov ARG2, RB
- //| mov L:RB, SAVE_L
- //| mov ARG3, RC
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k)
- //| // TValue * (finished) or NULL (metamethod) returned in eax (RC).
- //| mov BASE, L:RB->base
- //| test RC, RC
- //| jz >3
- //| // NOBARRIER: lj_meta_tset ensures the table is not black.
- //| movzx RA, PC_RA
- //|.if X64
- //| mov RBa, [BASE+RA*8]
- //| mov [RC], RBa
- //|.else
- //| mov RB, [BASE+RA*8+4]
- //| mov RA, [BASE+RA*8]
- //| mov [RC+4], RB
- //| mov [RC], RA
- //|.endif
- //|->cont_nop: // BASE = base, (RC = result)
- //| ins_next
- //|
- //|3: // Call __newindex metamethod.
- //| // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
- //| mov RA, L:RB->top
- dasm_put(Dst, 1171, BC_GSET, DISPATCH_GL(tmptv), LJ_TTAB, LJ_TISNUM, Dt1(->base), Dt1(->base));
- #line 1000 "vm_x86.dasc"
- //| mov [RA-12], PC // [cont|PC]
- //| movzx RC, PC_RA
- //| // Copy value to third argument.
- //|.if X64
- //| mov RBa, [BASE+RC*8]
- //| mov [RA+16], RBa
- //|.else
- //| mov RB, [BASE+RC*8+4]
- //| mov RC, [BASE+RC*8]
- //| mov [RA+20], RB
- //| mov [RA+16], RC
- //|.endif
- //| lea PC, [RA+FRAME_CONT]
- //| sub PC, BASE
- //| mov LFUNC:RB, [RA-8] // Guaranteed to be a function here.
- //| mov NARGS:RD, 3+1 // 3 args for func(t, k, v).
- //| jmp ->vm_call_dispatch_f
- //|
- //|->vmeta_tsetr:
- //|.if X64WIN
- //| mov L:CARG1d, SAVE_L
- //| mov CARG3d, RC
- //| mov L:CARG1d->base, BASE
- //| xchg CARG2d, TAB:RB // Caveat: CARG2d == BASE.
- //|.elif X64
- //| mov L:CARG1d, SAVE_L
- //| mov CARG2d, TAB:RB
- //| mov L:CARG1d->base, BASE
- //| mov RB, BASE // Save BASE.
- //| mov CARG3d, RC // Caveat: CARG3d == BASE.
- //|.else
- //| mov L:RA, SAVE_L
- //| mov ARG2, TAB:RB
- //| mov RB, BASE // Save BASE.
- //| mov ARG3, RC
- //| mov ARG1, L:RA
- //| mov L:RA->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key)
- //| // TValue * returned in eax (RC).
- //| movzx RA, PC_RA
- //| mov BASE, RB // Restore BASE.
- //| jmp ->BC_TSETR_Z
- //|
- //|//-- Comparison metamethods ---------------------------------------------
- //|
- //|->vmeta_comp:
- //|.if X64
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG2d/CARG3d == BASE.
- //|.if X64WIN
- //| lea CARG3d, [BASE+RD*8]
- //| lea CARG2d, [BASE+RA*8]
- //|.else
- //| lea CARG2d, [BASE+RA*8]
- //| lea CARG3d, [BASE+RD*8]
- //|.endif
- //| mov CARG1d, L:RB // Caveat: CARG1d/CARG4d == RA.
- //| movzx CARG4d, PC_OP
- //|.else
- //| movzx RB, PC_OP
- //| lea RD, [BASE+RD*8]
- //| lea RA, [BASE+RA*8]
- //| mov ARG4, RB
- //| mov L:RB, SAVE_L
- //| mov ARG3, RD
- //| mov ARG2, RA
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op)
- //| // 0/1 or TValue * (metamethod) returned in eax (RC).
- //|3:
- //| mov BASE, L:RB->base
- //| cmp RC, 1
- //| ja ->vmeta_binop
- //|4:
- //| lea PC, [PC+4]
- //| jb >6
- //|5:
- //| movzx RD, PC_RD
- //| branchPC RD
- //|6:
- //| ins_next
- dasm_put(Dst, 1316, Dt1(->top), FRAME_CONT, 3+1, Dt1(->base), Dt1(->base), Dt1(->base), -BCBIAS_J*4);
- #line 1086 "vm_x86.dasc"
- //|
- //|->cont_condt: // BASE = base, RC = result
- //| add PC, 4
- //| cmp dword [RC+4], LJ_TISTRUECOND // Branch if result is true.
- //| jb <5
- //| jmp <6
- //|
- //|->cont_condf: // BASE = base, RC = result
- //| cmp dword [RC+4], LJ_TISTRUECOND // Branch if result is false.
- //| jmp <4
- //|
- //|->vmeta_equal:
- //| sub PC, 4
- //|.if X64WIN
- //| mov CARG3d, RD
- //| mov CARG4d, RB
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG2d == BASE.
- //| mov CARG2d, RA
- //| mov CARG1d, L:RB // Caveat: CARG1d == RA.
- //|.elif X64
- //| mov CARG2d, RA
- //| mov CARG4d, RB // Caveat: CARG4d == RA.
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG3d == BASE.
- //| mov CARG3d, RD
- //| mov CARG1d, L:RB
- //|.else
- //| mov ARG4, RB
- //| mov L:RB, SAVE_L
- //| mov ARG3, RD
- //| mov ARG2, RA
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne)
- //| // 0/1 or TValue * (metamethod) returned in eax (RC).
- //| jmp <3
- //|
- //|->vmeta_equal_cd:
- //|.if FFI
- //| sub PC, 4
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov FCARG1, L:RB
- //| mov FCARG2, dword [PC-4]
- //| mov SAVE_PC, PC
- //| call extern lj_meta_equal_cd@8 // (lua_State *L, BCIns ins)
- //| // 0/1 or TValue * (metamethod) returned in eax (RC).
- //| jmp <3
- //|.endif
- //|
- //|->vmeta_istype:
- //|.if X64
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE.
- //| mov CARG2d, RA
- dasm_put(Dst, 1455, LJ_TISTRUECOND, LJ_TISTRUECOND, Dt1(->base), Dt1(->base), Dt1(->base));
- #line 1144 "vm_x86.dasc"
- //| movzx CARG3d, PC_RD
- //| mov L:CARG1d, L:RB
- //|.else
- //| movzx RD, PC_RD
- //| mov ARG2, RA
- //| mov L:RB, SAVE_L
- //| mov ARG3, RD
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp)
- //| mov BASE, L:RB->base
- //| jmp <6
- //|
- //|//-- Arithmetic metamethods ---------------------------------------------
- //|
- //|->vmeta_arith_vno:
- //|.if DUALNUM
- //| movzx RB, PC_RB
- //|.endif
- //|->vmeta_arith_vn:
- //| lea RC, [KBASE+RC*8]
- //| jmp >1
- //|
- //|->vmeta_arith_nvo:
- //|.if DUALNUM
- //| movzx RC, PC_RC
- //|.endif
- //|->vmeta_arith_nv:
- //| lea RC, [KBASE+RC*8]
- //| lea RB, [BASE+RB*8]
- //| xchg RB, RC
- //| jmp >2
- //|
- //|->vmeta_unm:
- //| lea RC, [BASE+RD*8]
- //| mov RB, RC
- //| jmp >2
- //|
- //|->vmeta_arith_vvo:
- //|.if DUALNUM
- //| movzx RB, PC_RB
- //|.endif
- //|->vmeta_arith_vv:
- //| lea RC, [BASE+RC*8]
- //|1:
- //| lea RB, [BASE+RB*8]
- //|2:
- //| lea RA, [BASE+RA*8]
- //|.if X64WIN
- //| mov CARG3d, RB
- //| mov CARG4d, RC
- //| movzx RC, PC_OP
- //| mov ARG5d, RC
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG2d == BASE.
- //| mov CARG2d, RA
- //| mov CARG1d, L:RB // Caveat: CARG1d == RA.
- //|.elif X64
- //| movzx CARG5d, PC_OP
- //| mov CARG2d, RA
- //| mov CARG4d, RC // Caveat: CARG4d == RA.
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE // Caveat: CARG3d == BASE.
- //| mov CARG3d, RB
- //| mov L:RB, L:CARG1d
- //|.else
- //| mov ARG3, RB
- //| mov L:RB, SAVE_L
- //| mov ARG4, RC
- //| movzx RC, PC_OP
- //| mov ARG2, RA
- //| mov ARG5, RC
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
- //| // NULL (finished) or TValue * (metamethod) returned in eax (RC).
- //| mov BASE, L:RB->base
- //| test RC, RC
- dasm_put(Dst, 1581, Dt1(->base), Dt1(->base), Dt1(->base));
- #line 1226 "vm_x86.dasc"
- //| jz ->cont_nop
- //|
- //| // Call metamethod for binary op.
- //|->vmeta_binop:
- //| // BASE = base, RC = new base, stack = cont/func/o1/o2
- //| mov RA, RC
- //| sub RC, BASE
- //| mov [RA-12], PC // [cont|PC]
- //| lea PC, [RC+FRAME_CONT]
- //| mov NARGS:RD, 2+1 // 2 args for func(o1, o2).
- //| jmp ->vm_call_dispatch
- //|
- //|->vmeta_len:
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| lea FCARG2, [BASE+RD*8] // Caveat: FCARG2 == BASE
- //| mov L:FCARG1, L:RB
- //| mov SAVE_PC, PC
- //| call extern lj_meta_len@8 // (lua_State *L, TValue *o)
- //| // NULL (retry) or TValue * (metamethod) returned in eax (RC).
- //| mov BASE, L:RB->base
- dasm_put(Dst, 1714, FRAME_CONT, 2+1, Dt1(->base), Dt1(->base));
- #line 1247 "vm_x86.dasc"
- #if LJ_52
- //| test RC, RC
- //| jne ->vmeta_binop // Binop call for compatibility.
- //| movzx RD, PC_RD
- //| mov TAB:FCARG1, [BASE+RD*8]
- //| jmp ->BC_LEN_Z
- dasm_put(Dst, 1766);
- #line 1253 "vm_x86.dasc"
- #else
- //| jmp ->vmeta_binop // Binop call for compatibility.
- dasm_put(Dst, 1785);
- #line 1255 "vm_x86.dasc"
- #endif
- //|
- //|//-- Call metamethod ----------------------------------------------------
- //|
- //|->vmeta_call_ra:
- //| lea RA, [BASE+RA*8+8]
- //|->vmeta_call: // Resolve and call __call metamethod.
- //| // BASE = old base, RA = new base, RC = nargs+1, PC = return
- //| mov TMP2, RA // Save RA, RC for us.
- //| mov TMP1, NARGS:RD
- //| sub RA, 8
- //|.if X64
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE.
- //| mov CARG2d, RA
- //| lea CARG3d, [RA+NARGS:RD*8]
- //| mov CARG1d, L:RB // Caveat: CARG1d may be RA.
- //|.else
- //| lea RC, [RA+NARGS:RD*8]
- //| mov L:RB, SAVE_L
- //| mov ARG2, RA
- //| mov ARG3, RC
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE // This is the callers base!
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
- //| mov BASE, L:RB->base
- //| mov RA, TMP2
- //| mov NARGS:RD, TMP1
- //| mov LFUNC:RB, [RA-8]
- //| add NARGS:RD, 1
- //| // This is fragile. L->base must not move, KBASE must always be defined.
- //| cmp KBASE, BASE // Continue with CALLT if flag set.
- //| je ->BC_CALLT_Z
- //| mov BASE, RA
- //| ins_call // Otherwise call resolved metamethod.
- //|
- //|//-- Argument coercion for 'for' statement ------------------------------
- //|
- //|->vmeta_for:
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov FCARG2, RA // Caveat: FCARG2 == BASE
- //| mov L:FCARG1, L:RB // Caveat: FCARG1 == RA
- //| mov SAVE_PC, PC
- //| call extern lj_meta_for@8 // (lua_State *L, TValue *base)
- //| mov BASE, L:RB->base
- //| mov RC, [PC-4]
- //| movzx RA, RCH
- //| movzx OP, RCL
- //| shr RC, 16
- //|.if X64
- //| jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Retry FORI or JFORI.
- //|.else
- //| jmp aword [DISPATCH+OP*4+GG_DISP2STATIC] // Retry FORI or JFORI.
- //|.endif
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Fast functions -----------------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|.macro .ffunc, name
- //|->ff_ .. name:
- //|.endmacro
- //|
- //|.macro .ffunc_1, name
- //|->ff_ .. name:
- //| cmp NARGS:RD, 1+1; jb ->fff_fallback
- //|.endmacro
- //|
- //|.macro .ffunc_2, name
- //|->ff_ .. name:
- //| cmp NARGS:RD, 2+1; jb ->fff_fallback
- //|.endmacro
- //|
- //|.macro .ffunc_nsse, name, op
- //| .ffunc_1 name
- //| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
- //| op xmm0, qword [BASE]
- //|.endmacro
- //|
- //|.macro .ffunc_nsse, name
- //| .ffunc_nsse name, movsd
- //|.endmacro
- //|
- //|.macro .ffunc_nnsse, name
- //| .ffunc_2 name
- //| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
- //| cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback
- //| movsd xmm0, qword [BASE]
- //| movsd xmm1, qword [BASE+8]
- //|.endmacro
- //|
- //|.macro .ffunc_nnr, name
- //| .ffunc_2 name
- //| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
- //| cmp dword [BASE+12], LJ_TISNUM; jae ->fff_fallback
- //| fld qword [BASE+8]
- //| fld qword [BASE]
- //|.endmacro
- //|
- //|// Inlined GC threshold check. Caveat: uses label 1.
- //|.macro ffgccheck
- //| mov RB, [DISPATCH+DISPATCH_GL(gc.total)]
- //| cmp RB, [DISPATCH+DISPATCH_GL(gc.threshold)]
- //| jb >1
- //| call ->fff_gcstep
- //|1:
- //|.endmacro
- //|
- //|//-- Base library: checks -----------------------------------------------
- //|
- //|.ffunc_1 assert
- //| mov RB, [BASE+4]
- //| cmp RB, LJ_TISTRUECOND; jae ->fff_fallback
- //| mov PC, [BASE-4]
- //| mov MULTRES, RD
- //| mov [BASE-4], RB
- //| mov RB, [BASE]
- //| mov [BASE-8], RB
- //| sub RD, 2
- //| jz >2
- //| mov RA, BASE
- dasm_put(Dst, 1790, Dt1(->base), Dt1(->base), Dt7(->pc), Dt1(->base), Dt1(->base), GG_DISP2STATIC, 1+1, LJ_TISTRUECOND);
- #line 1379 "vm_x86.dasc"
- //|1:
- //| add RA, 8
- //|.if X64
- //| mov RBa, [RA]
- //| mov [RA-8], RBa
- //|.else
- //| mov RB, [RA+4]
- //| mov [RA-4], RB
- //| mov RB, [RA]
- //| mov [RA-8], RB
- //|.endif
- //| sub RD, 1
- //| jnz <1
- //|2:
- //| mov RD, MULTRES
- //| jmp ->fff_res_
- //|
- //|.ffunc_1 type
- //| mov RB, [BASE+4]
- //|.if X64
- //| mov RA, RB
- //| sar RA, 15
- //| cmp RA, -2
- //| je >3
- //|.endif
- //| mov RC, ~LJ_TNUMX
- //| not RB
- //| cmp RC, RB
- //| cmova RC, RB
- //|2:
- //| mov CFUNC:RB, [BASE-8]
- //| mov STR:RC, [CFUNC:RB+RC*8+((char *)(&((GCfuncC *)0)->upvalue))]
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], LJ_TSTR
- //| mov [BASE-8], STR:RC
- //| jmp ->fff_res1
- //|.if X64
- //|3:
- //| mov RC, ~LJ_TLIGHTUD
- //| jmp <2
- dasm_put(Dst, 1976, 1+1, ~LJ_TNUMX, ((char *)(&((GCfuncC *)0)->upvalue)), LJ_TSTR, ~LJ_TLIGHTUD);
- #line 1419 "vm_x86.dasc"
- //|.endif
- //|
- //|//-- Base library: getters and setters ---------------------------------
- //|
- //|.ffunc_1 getmetatable
- //| mov RB, [BASE+4]
- //| mov PC, [BASE-4]
- //| cmp RB, LJ_TTAB; jne >6
- //|1: // Field metatable must be at same offset for GCtab and GCudata!
- //| mov TAB:RB, [BASE]
- //| mov TAB:RB, TAB:RB->metatable
- //|2:
- //| test TAB:RB, TAB:RB
- //| mov dword [BASE-4], LJ_TNIL
- //| jz ->fff_res1
- //| mov STR:RC, [DISPATCH+DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable)]
- //| mov dword [BASE-4], LJ_TTAB // Store metatable as default result.
- //| mov [BASE-8], TAB:RB
- //| mov RA, TAB:RB->hmask
- //| and RA, STR:RC->hash
- //| imul RA, #NODE
- //| add NODE:RA, TAB:RB->node
- dasm_put(Dst, 2080, 1+1, LJ_TTAB, Dt6(->metatable), LJ_TNIL, DISPATCH_GL(gcroot)+4*(GCROOT_MMNAME+MM_metatable), LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node));
- #line 1441 "vm_x86.dasc"
- //|3: // Rearranged logic, because we expect _not_ to find the key.
- //| cmp dword NODE:RA->key.it, LJ_TSTR
- //| jne >4
- //| cmp dword NODE:RA->key.gcr, STR:RC
- //| je >5
- //|4:
- //| mov NODE:RA, NODE:RA->next
- //| test NODE:RA, NODE:RA
- //| jnz <3
- //| jmp ->fff_res1 // Not found, keep default result.
- //|5:
- //| mov RB, [RA+4]
- //| cmp RB, LJ_TNIL; je ->fff_res1 // Ditto for nil value.
- //| mov RC, [RA]
- //| mov [BASE-4], RB // Return value of mt.__metatable.
- //| mov [BASE-8], RC
- //| jmp ->fff_res1
- //|
- //|6:
- //| cmp RB, LJ_TUDATA; je <1
- dasm_put(Dst, 2153, Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), DtB(->next), LJ_TNIL);
- #line 1461 "vm_x86.dasc"
- //|.if X64
- //| cmp RB, LJ_TNUMX; ja >8
- //| cmp RB, LJ_TISNUM; jbe >7
- //| mov RB, LJ_TLIGHTUD
- //| jmp >8
- //|7:
- //|.else
- //| cmp RB, LJ_TISNUM; ja >8
- //|.endif
- //| mov RB, LJ_TNUMX
- //|8:
- //| not RB
- //| mov TAB:RB, [DISPATCH+RB*4+DISPATCH_GL(gcroot[GCROOT_BASEMT])]
- //| jmp <2
- //|
- //|.ffunc_2 setmetatable
- dasm_put(Dst, 2218, LJ_TUDATA, LJ_TNUMX, LJ_TISNUM, LJ_TLIGHTUD, LJ_TNUMX, DISPATCH_GL(gcroot[GCROOT_BASEMT]), 2+1);
- #line 1477 "vm_x86.dasc"
- //| cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback
- //| // Fast path: no mt for table yet and not clearing the mt.
- //| mov TAB:RB, [BASE]
- //| cmp dword TAB:RB->metatable, 0; jne ->fff_fallback
- //| cmp dword [BASE+12], LJ_TTAB; jne ->fff_fallback
- //| mov TAB:RC, [BASE+8]
- //| mov TAB:RB->metatable, TAB:RC
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], LJ_TTAB // Return original table.
- //| mov [BASE-8], TAB:RB
- //| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
- //| jz >1
- //| // Possible write barrier. Table is black, but skip iswhite(mt) check.
- //| barrierback TAB:RB, RC
- dasm_put(Dst, 2274, LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->metatable), LJ_TTAB, Dt6(->marked), LJ_GC_BLACK, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain));
- #line 1491 "vm_x86.dasc"
- //|1:
- //| jmp ->fff_res1
- //|
- //|.ffunc_2 rawget
- //| cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback
- //|.if X64WIN
- //| mov RB, BASE // Save BASE.
- //| lea CARG3d, [BASE+8]
- //| mov CARG2d, [BASE] // Caveat: CARG2d == BASE.
- //| mov CARG1d, SAVE_L
- //|.elif X64
- //| mov RB, BASE // Save BASE.
- //| mov CARG2d, [BASE]
- //| lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE.
- //| mov CARG1d, SAVE_L
- //|.else
- //| mov TAB:RD, [BASE]
- //| mov L:RB, SAVE_L
- //| mov ARG2, TAB:RD
- //| mov ARG1, L:RB
- //| mov RB, BASE // Save BASE.
- //| add BASE, 8
- //| mov ARG3, BASE
- //|.endif
- //| call extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key)
- //| // cTValue * returned in eax (RD).
- //| mov BASE, RB // Restore BASE.
- //| // Copy table slot.
- //|.if X64
- //| mov RBa, [RD]
- //| mov PC, [BASE-4]
- //| mov [BASE-8], RBa
- //|.else
- //| mov RB, [RD]
- //| mov RD, [RD+4]
- //| mov PC, [BASE-4]
- //| mov [BASE-8], RB
- //| mov [BASE-4], RD
- //|.endif
- //| jmp ->fff_res1
- //|
- //|//-- Base library: conversions ------------------------------------------
- //|
- //|.ffunc tonumber
- //| // Only handles the number case inline (without a base argument).
- //| cmp NARGS:RD, 1+1; jne ->fff_fallback // Exactly one argument.
- //| cmp dword [BASE+4], LJ_TISNUM
- //|.if DUALNUM
- //| jne >1
- //| mov RB, dword [BASE]; jmp ->fff_resi
- dasm_put(Dst, 2343, DISPATCH_GL(gc.grayagain), Dt6(->gclist), 2+1, LJ_TTAB, 1+1, LJ_TISNUM);
- #line 1541 "vm_x86.dasc"
- //|1:
- //| ja ->fff_fallback
- //|.else
- //| jae ->fff_fallback
- //|.endif
- //| movsd xmm0, qword [BASE]; jmp ->fff_resxmm0
- //|
- //|.ffunc_1 tostring
- //| // Only handles the string or number case inline.
- //| mov PC, [BASE-4]
- //| cmp dword [BASE+4], LJ_TSTR; jne >3
- //| // A __tostring method in the string base metatable is ignored.
- //| mov STR:RD, [BASE]
- //|2:
- //| mov dword [BASE-4], LJ_TSTR
- //| mov [BASE-8], STR:RD
- //| jmp ->fff_res1
- //|3: // Handle numbers inline, unless a number base metatable is present.
- //| cmp dword [BASE+4], LJ_TISNUM; ja ->fff_fallback
- dasm_put(Dst, 2429, 1+1, LJ_TSTR, LJ_TSTR, LJ_TISNUM);
- #line 1560 "vm_x86.dasc"
- //| cmp dword [DISPATCH+DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])], 0
- //| jne ->fff_fallback
- //| ffgccheck // Caveat: uses label 1.
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Add frame since C call can throw.
- //| mov SAVE_PC, PC // Redundant (but a defined value).
- //|.if X64 and not X64WIN
- //| mov FCARG2, BASE // Otherwise: FCARG2 == BASE
- //|.endif
- //| mov L:FCARG1, L:RB
- //|.if DUALNUM
- //| call extern lj_strfmt_number@8 // (lua_State *L, cTValue *o)
- //|.else
- //| call extern lj_strfmt_num@8 // (lua_State *L, lua_Number *np)
- //|.endif
- //| // GCstr returned in eax (RD).
- //| mov BASE, L:RB->base
- //| jmp <2
- //|
- //|//-- Base library: iterators -------------------------------------------
- //|
- //|.ffunc_1 next
- //| je >2 // Missing 2nd arg?
- dasm_put(Dst, 2498, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), Dt1(->base), 1+1);
- #line 1583 "vm_x86.dasc"
- //|1:
- //| cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Add frame since C call can throw.
- //| mov L:RB->top, BASE // Dummy frame length is ok.
- //| mov PC, [BASE-4]
- //|.if X64WIN
- //| lea CARG3d, [BASE+8]
- //| mov CARG2d, [BASE] // Caveat: CARG2d == BASE.
- //| mov CARG1d, L:RB
- //|.elif X64
- //| mov CARG2d, [BASE]
- //| lea CARG3d, [BASE+8] // Caveat: CARG3d == BASE.
- //| mov CARG1d, L:RB
- //|.else
- //| mov TAB:RD, [BASE]
- //| mov ARG2, TAB:RD
- //| mov ARG1, L:RB
- //| add BASE, 8
- //| mov ARG3, BASE
- //|.endif
- //| mov SAVE_PC, PC // Needed for ITERN fallback.
- //| call extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key)
- //| // Flag returned in eax (RD).
- //| mov BASE, L:RB->base
- //| test RD, RD; jz >3 // End of traversal?
- //| // Copy key and value to results.
- //|.if X64
- //| mov RBa, [BASE+8]
- //| mov RDa, [BASE+16]
- //| mov [BASE-8], RBa
- //| mov [BASE], RDa
- //|.else
- //| mov RB, [BASE+8]
- //| mov RD, [BASE+12]
- //| mov [BASE-8], RB
- //| mov [BASE-4], RD
- //| mov RB, [BASE+16]
- //| mov RD, [BASE+20]
- //| mov [BASE], RB
- //| mov [BASE+4], RD
- //|.endif
- //|->fff_res2:
- //| mov RD, 1+2
- //| jmp ->fff_res
- //|2: // Set missing 2nd arg to nil.
- //| mov dword [BASE+12], LJ_TNIL
- //| jmp <1
- //|3: // End of traversal: return nil.
- //| mov dword [BASE-4], LJ_TNIL
- dasm_put(Dst, 2566, LJ_TTAB, Dt1(->base), Dt1(->top), Dt1(->base), 1+2, LJ_TNIL);
- #line 1633 "vm_x86.dasc"
- //| jmp ->fff_res1
- //|
- //|.ffunc_1 pairs
- //| mov TAB:RB, [BASE]
- //| cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback
- dasm_put(Dst, 2657, LJ_TNIL, 1+1, LJ_TTAB);
- #line 1638 "vm_x86.dasc"
- #if LJ_52
- //| cmp dword TAB:RB->metatable, 0; jne ->fff_fallback
- dasm_put(Dst, 2688, Dt6(->metatable));
- #line 1640 "vm_x86.dasc"
- #endif
- //| mov CFUNC:RB, [BASE-8]
- //| mov CFUNC:RD, CFUNC:RB->upvalue[0]
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], LJ_TFUNC
- //| mov [BASE-8], CFUNC:RD
- //| mov dword [BASE+12], LJ_TNIL
- //| mov RD, 1+3
- //| jmp ->fff_res
- //|
- //|.ffunc_2 ipairs_aux
- //| cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback
- //| cmp dword [BASE+12], LJ_TISNUM
- //|.if DUALNUM
- //| jne ->fff_fallback
- //|.else
- //| jae ->fff_fallback
- //|.endif
- //| mov PC, [BASE-4]
- //|.if DUALNUM
- //| mov RD, dword [BASE+8]
- //| add RD, 1
- //| mov dword [BASE-4], LJ_TISNUM
- //| mov dword [BASE-8], RD
- //|.else
- //| movsd xmm0, qword [BASE+8]
- //| sseconst_1 xmm1, RBa
- //| addsd xmm0, xmm1
- //| cvttsd2si RD, xmm0
- //| movsd qword [BASE-8], xmm0
- //|.endif
- //| mov TAB:RB, [BASE]
- //| cmp RD, TAB:RB->asize; jae >2 // Not in array part?
- //| shl RD, 3
- dasm_put(Dst, 2697, Dt8(->upvalue[0]), LJ_TFUNC, LJ_TNIL, 1+3, 2+1, LJ_TTAB, LJ_TISNUM, LJ_TISNUM, Dt6(->asize));
- #line 1674 "vm_x86.dasc"
- //| add RD, TAB:RB->array
- //|1:
- //| cmp dword [RD+4], LJ_TNIL; je ->fff_res0
- //| // Copy array slot.
- //|.if X64
- //| mov RBa, [RD]
- //| mov [BASE], RBa
- //|.else
- //| mov RB, [RD]
- //| mov RD, [RD+4]
- //| mov [BASE], RB
- //| mov [BASE+4], RD
- //|.endif
- //| jmp ->fff_res2
- //|2: // Check for empty hash part first. Otherwise call C function.
- //| cmp dword TAB:RB->hmask, 0; je ->fff_res0
- //| mov FCARG1, TAB:RB
- //| mov RB, BASE // Save BASE.
- //| mov FCARG2, RD // Caveat: FCARG2 == BASE
- //| call extern lj_tab_getinth@8 // (GCtab *t, int32_t key)
- //| // cTValue * or NULL returned in eax (RD).
- //| mov BASE, RB
- //| test RD, RD
- //| jnz <1
- //|->fff_res0:
- //| mov RD, 1+0
- //| jmp ->fff_res
- //|
- //|.ffunc_1 ipairs
- //| mov TAB:RB, [BASE]
- dasm_put(Dst, 2784, Dt6(->array), LJ_TNIL, Dt6(->hmask), 1+0, 1+1);
- #line 1704 "vm_x86.dasc"
- //| cmp dword [BASE+4], LJ_TTAB; jne ->fff_fallback
- dasm_put(Dst, 2676, LJ_TTAB);
- #line 1705 "vm_x86.dasc"
- #if LJ_52
- //| cmp dword TAB:RB->metatable, 0; jne ->fff_fallback
- dasm_put(Dst, 2688, Dt6(->metatable));
- #line 1707 "vm_x86.dasc"
- #endif
- //| mov CFUNC:RB, [BASE-8]
- //| mov CFUNC:RD, CFUNC:RB->upvalue[0]
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], LJ_TFUNC
- //| mov [BASE-8], CFUNC:RD
- //|.if DUALNUM
- //| mov dword [BASE+12], LJ_TISNUM
- //| mov dword [BASE+8], 0
- //|.else
- //| xorps xmm0, xmm0
- //| movsd qword [BASE+8], xmm0
- //|.endif
- //| mov RD, 1+3
- //| jmp ->fff_res
- //|
- //|//-- Base library: catch errors ----------------------------------------
- //|
- //|.ffunc_1 pcall
- //| lea RA, [BASE+8]
- //| sub NARGS:RD, 1
- //| mov PC, 8+FRAME_PCALL
- //|1:
- //| movzx RB, byte [DISPATCH+DISPATCH_GL(hookmask)]
- //| shr RB, HOOK_ACTIVE_SHIFT
- //| and RB, 1
- //| add PC, RB // Remember active hook before pcall.
- //| jmp ->vm_call_dispatch
- //|
- //|.ffunc_2 xpcall
- //| cmp dword [BASE+12], LJ_TFUNC; jne ->fff_fallback
- dasm_put(Dst, 2860, Dt8(->upvalue[0]), LJ_TFUNC, LJ_TISNUM, 1+3, 1+1, 8+FRAME_PCALL, DISPATCH_GL(hookmask), HOOK_ACTIVE_SHIFT, 2+1);
- #line 1738 "vm_x86.dasc"
- //| mov RB, [BASE+4] // Swap function and traceback.
- //| mov [BASE+12], RB
- //| mov dword [BASE+4], LJ_TFUNC
- //| mov LFUNC:RB, [BASE]
- //| mov PC, [BASE+8]
- //| mov [BASE+8], LFUNC:RB
- //| mov [BASE], PC
- //| lea RA, [BASE+16]
- //| sub NARGS:RD, 2
- //| mov PC, 16+FRAME_PCALL
- //| jmp <1
- //|
- //|//-- Coroutine library --------------------------------------------------
- //|
- //|.macro coroutine_resume_wrap, resume
- //|.if resume
- //|.ffunc_1 coroutine_resume
- //| mov L:RB, [BASE]
- //|.else
- //|.ffunc coroutine_wrap_aux
- //| mov CFUNC:RB, [BASE-8]
- //| mov L:RB, CFUNC:RB->upvalue[0].gcr
- //|.endif
- //| mov PC, [BASE-4]
- //| mov SAVE_PC, PC
- //|.if X64
- //| mov TMP1, L:RB
- //|.else
- //| mov ARG1, L:RB
- //|.endif
- //|.if resume
- //| cmp dword [BASE+4], LJ_TTHREAD; jne ->fff_fallback
- //|.endif
- //| cmp aword L:RB->cframe, 0; jne ->fff_fallback
- //| cmp byte L:RB->status, LUA_YIELD; ja ->fff_fallback
- //| mov RA, L:RB->top
- //| je >1 // Status != LUA_YIELD (i.e. 0)?
- //| cmp RA, L:RB->base // Check for presence of initial func.
- //| je ->fff_fallback
- //|1:
- //|.if resume
- //| lea PC, [RA+NARGS:RD*8-16] // Check stack space (-1-thread).
- //|.else
- //| lea PC, [RA+NARGS:RD*8-8] // Check stack space (-1).
- //|.endif
- //| cmp PC, L:RB->maxstack; ja ->fff_fallback
- //| mov L:RB->top, PC
- //|
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //|.if resume
- //| add BASE, 8 // Keep resumed thread in stack for GC.
- //|.endif
- //| mov L:RB->top, BASE
- //|.if resume
- //| lea RB, [BASE+NARGS:RD*8-24] // RB = end of source for stack move.
- //|.else
- //| lea RB, [BASE+NARGS:RD*8-16] // RB = end of source for stack move.
- //|.endif
- //| sub RBa, PCa // Relative to PC.
- //|
- //| cmp PC, RA
- //| je >3
- //|2: // Move args to coroutine.
- //|.if X64
- //| mov RCa, [PC+RB]
- //| mov [PC-8], RCa
- //|.else
- //| mov RC, [PC+RB+4]
- //| mov [PC-4], RC
- //| mov RC, [PC+RB]
- //| mov [PC-8], RC
- //|.endif
- //| sub PC, 8
- //| cmp PC, RA
- //| jne <2
- //|3:
- //|.if X64
- //| mov CARG2d, RA
- //| mov CARG1d, TMP1
- //|.else
- //| mov ARG2, RA
- //| xor RA, RA
- //| mov ARG4, RA
- //| mov ARG3, RA
- //|.endif
- //| call ->vm_resume // (lua_State *L, TValue *base, 0, 0)
- //|
- //| mov L:RB, SAVE_L
- //|.if X64
- //| mov L:PC, TMP1
- //|.else
- //| mov L:PC, ARG1 // The callee doesn't modify SAVE_L.
- //|.endif
- //| mov BASE, L:RB->base
- //| mov [DISPATCH+DISPATCH_GL(cur_L)], L:RB
- //| set_vmstate INTERP
- //|
- //| cmp eax, LUA_YIELD
- //| ja >8
- //|4:
- //| mov RA, L:PC->base
- //| mov KBASE, L:PC->top
- //| mov L:PC->top, RA // Clear coroutine stack.
- //| mov PC, KBASE
- //| sub PC, RA
- //| je >6 // No results?
- //| lea RD, [BASE+PC]
- //| shr PC, 3
- //| cmp RD, L:RB->maxstack
- //| ja >9 // Need to grow stack?
- //|
- //| mov RB, BASE
- //| sub RBa, RAa
- //|5: // Move results from coroutine.
- //|.if X64
- //| mov RDa, [RA]
- //| mov [RA+RB], RDa
- //|.else
- //| mov RD, [RA]
- //| mov [RA+RB], RD
- //| mov RD, [RA+4]
- //| mov [RA+RB+4], RD
- //|.endif
- //| add RA, 8
- //| cmp RA, KBASE
- //| jne <5
- //|6:
- //|.if resume
- //| lea RD, [PC+2] // nresults+1 = 1 + true + results.
- //| mov dword [BASE-4], LJ_TTRUE // Prepend true to results.
- //|.else
- //| lea RD, [PC+1] // nresults+1 = 1 + results.
- //|.endif
- //|7:
- //| mov PC, SAVE_PC
- //| mov MULTRES, RD
- //|.if resume
- //| mov RAa, -8
- //|.else
- //| xor RA, RA
- //|.endif
- //| test PC, FRAME_TYPE
- //| jz ->BC_RET_Z
- //| jmp ->vm_return
- //|
- //|8: // Coroutine returned with error (at co->top-1).
- //|.if resume
- //| mov dword [BASE-4], LJ_TFALSE // Prepend false to results.
- //| mov RA, L:PC->top
- //| sub RA, 8
- //| mov L:PC->top, RA // Clear error from coroutine stack.
- //| // Copy error message.
- //|.if X64
- //| mov RDa, [RA]
- //| mov [BASE], RDa
- //|.else
- //| mov RD, [RA]
- //| mov [BASE], RD
- //| mov RD, [RA+4]
- //| mov [BASE+4], RD
- //|.endif
- //| mov RD, 1+2 // nresults+1 = 1 + false + error.
- //| jmp <7
- //|.else
- //| mov FCARG2, L:PC
- //| mov FCARG1, L:RB
- //| call extern lj_ffh_coroutine_wrap_err@8 // (lua_State *L, lua_State *co)
- //| // Error function does not return.
- //|.endif
- //|
- //|9: // Handle stack expansion on return from yield.
- //|.if X64
- //| mov L:RA, TMP1
- //|.else
- //| mov L:RA, ARG1 // The callee doesn't modify SAVE_L.
- //|.endif
- //| mov L:RA->top, KBASE // Undo coroutine stack clearing.
- //| mov FCARG2, PC
- //| mov FCARG1, L:RB
- //| call extern lj_state_growstack@8 // (lua_State *L, int n)
- //|.if X64
- //| mov L:PC, TMP1
- //|.else
- //| mov L:PC, ARG1
- //|.endif
- //| mov BASE, L:RB->base
- //| jmp <4 // Retry the stack move.
- //|.endmacro
- //|
- //| coroutine_resume_wrap 1 // coroutine.resume
- dasm_put(Dst, 2947, LJ_TFUNC, LJ_TFUNC, 16+FRAME_PCALL, 1+1, LJ_TTHREAD, Dt1(->cframe), Dt1(->status), LUA_YIELD);
- dasm_put(Dst, 3038, Dt1(->top), Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top));
- dasm_put(Dst, 3127, Dt1(->base), DISPATCH_GL(cur_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack));
- #line 1929 "vm_x86.dasc"
- //| coroutine_resume_wrap 0 // coroutine.wrap
- dasm_put(Dst, 3218, LJ_TTRUE, FRAME_TYPE, LJ_TFALSE, Dt1(->top), Dt1(->top), 1+2, Dt1(->top), Dt1(->base));
- dasm_put(Dst, 3319, Dt8(->upvalue[0].gcr), Dt1(->cframe), Dt1(->status), LUA_YIELD, Dt1(->top), Dt1(->base), Dt1(->maxstack), Dt1(->top), Dt1(->base));
- dasm_put(Dst, 3393, Dt1(->top), Dt1(->base), DISPATCH_GL(cur_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top));
- #line 1930 "vm_x86.dasc"
- //|
- //|.ffunc coroutine_yield
- //| mov L:RB, SAVE_L
- dasm_put(Dst, 3481, Dt1(->maxstack), FRAME_TYPE, Dt1(->top), Dt1(->base));
- #line 1933 "vm_x86.dasc"
- //| test aword L:RB->cframe, CFRAME_RESUME
- //| jz ->fff_fallback
- //| mov L:RB->base, BASE
- //| lea RD, [BASE+NARGS:RD*8-8]
- //| mov L:RB->top, RD
- //| xor RD, RD
- //| mov aword L:RB->cframe, RDa
- //| mov al, LUA_YIELD
- //| mov byte L:RB->status, al
- //| jmp ->vm_leave_unw
- //|
- //|//-- Math library -------------------------------------------------------
- //|
- //|.if not DUALNUM
- //|->fff_resi: // Dummy.
- //|.endif
- //|
- //|->fff_resn:
- //| mov PC, [BASE-4]
- //| fstp qword [BASE-8]
- //| jmp ->fff_res1
- //|
- //| .ffunc_1 math_abs
- //|.if DUALNUM
- //| cmp dword [BASE+4], LJ_TISNUM; jne >2
- //| mov RB, dword [BASE]
- dasm_put(Dst, 3601, Dt1(->cframe), CFRAME_RESUME, Dt1(->base), Dt1(->top), Dt1(->cframe), LUA_YIELD, Dt1(->status), 1+1, LJ_TISNUM);
- #line 1959 "vm_x86.dasc"
- //| cmp RB, 0; jns ->fff_resi
- //| neg RB; js >1
- //|->fff_resbit:
- //|->fff_resi:
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], LJ_TISNUM
- //| mov dword [BASE-8], RB
- //| jmp ->fff_res1
- //|1:
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], 0x41e00000 // 2^31.
- //| mov dword [BASE-8], 0
- //| jmp ->fff_res1
- //|2:
- //| ja ->fff_fallback
- //|.else
- //| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
- //|.endif
- //| movsd xmm0, qword [BASE]
- //| sseconst_abs xmm1, RDa
- //| andps xmm0, xmm1
- //|->fff_resxmm0:
- //| mov PC, [BASE-4]
- //| movsd qword [BASE-8], xmm0
- //| // fallthrough
- //|
- //|->fff_res1:
- //| mov RD, 1+1
- //|->fff_res:
- //| mov MULTRES, RD
- dasm_put(Dst, 3675, LJ_TISNUM, (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), 1+1);
- #line 1989 "vm_x86.dasc"
- //|->fff_res_:
- //| test PC, FRAME_TYPE
- //| jnz >7
- //|5:
- //| cmp PC_RB, RDL // More results expected?
- //| ja >6
- //| // Adjust BASE. KBASE is assumed to be set for the calling frame.
- //| movzx RA, PC_RA
- //| not RAa // Note: ~RA = -(RA+1)
- //| lea BASE, [BASE+RA*8] // base = base - (RA+1)*8
- //| ins_next
- //|
- //|6: // Fill up results with nil.
- //| mov dword [BASE+RD*8-12], LJ_TNIL
- //| add RD, 1
- //| jmp <5
- //|
- //|7: // Non-standard return case.
- //| mov RAa, -8 // Results start at BASE+RA = BASE-8.
- //| jmp ->vm_return
- //|
- //|.if X64
- //|.define fff_resfp, fff_resxmm0
- //|.else
- //|.define fff_resfp, fff_resn
- //|.endif
- //|
- //|.macro math_round, func
- //| .ffunc math_ .. func
- //|.if DUALNUM
- //| cmp dword [BASE+4], LJ_TISNUM; jne >1
- //| mov RB, dword [BASE]; jmp ->fff_resi
- //|1:
- //| ja ->fff_fallback
- //|.else
- //| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
- //|.endif
- //| movsd xmm0, qword [BASE]
- //| call ->vm_ .. func .. _sse
- //|.if DUALNUM
- //| cvttsd2si RB, xmm0
- //| cmp RB, 0x80000000
- //| jne ->fff_resi
- //| cvtsi2sd xmm1, RB
- //| ucomisd xmm0, xmm1
- //| jp ->fff_resxmm0
- //| je ->fff_resi
- //|.endif
- //| jmp ->fff_resxmm0
- //|.endmacro
- //|
- //| math_round floor
- dasm_put(Dst, 3782, FRAME_TYPE, LJ_TNIL, LJ_TISNUM);
- #line 2041 "vm_x86.dasc"
- //| math_round ceil
- dasm_put(Dst, 3890, LJ_TISNUM);
- #line 2042 "vm_x86.dasc"
- //|
- //|.ffunc_nsse math_sqrt, sqrtsd; jmp ->fff_resxmm0
- //|
- //|.ffunc math_log
- //| cmp NARGS:RD, 1+1; jne ->fff_fallback // Exactly one argument.
- dasm_put(Dst, 3963, 1+1, LJ_TISNUM);
- #line 2047 "vm_x86.dasc"
- //| cmp dword [BASE+4], LJ_TISNUM; jae ->fff_fallback
- //| movsd xmm0, qword [BASE]
- //|.if not X64
- //| movsd FPARG1, xmm0
- //|.endif
- //| mov RB, BASE
- //| call extern log
- //| mov BASE, RB
- //| jmp ->fff_resfp
- //|
- //|.macro math_extern, func
- //| .ffunc_nsse math_ .. func
- //|.if not X64
- //| movsd FPARG1, xmm0
- //|.endif
- //| mov RB, BASE
- //| call extern func
- //| mov BASE, RB
- //| jmp ->fff_resfp
- //|.endmacro
- //|
- //|.macro math_extern2, func
- //| .ffunc_nnsse math_ .. func
- //|.if not X64
- //| movsd FPARG1, xmm0
- //| movsd FPARG3, xmm1
- //|.endif
- //| mov RB, BASE
- //| call extern func
- //| mov BASE, RB
- //| jmp ->fff_resfp
- //|.endmacro
- //|
- //| math_extern log10
- //| math_extern exp
- dasm_put(Dst, 4039, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1);
- #line 2082 "vm_x86.dasc"
- //| math_extern sin
- //| math_extern cos
- dasm_put(Dst, 4122, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM);
- #line 2084 "vm_x86.dasc"
- //| math_extern tan
- //| math_extern asin
- //| math_extern acos
- dasm_put(Dst, 4206, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM);
- #line 2087 "vm_x86.dasc"
- //| math_extern atan
- //| math_extern sinh
- dasm_put(Dst, 4301, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1);
- #line 2089 "vm_x86.dasc"
- //| math_extern cosh
- //| math_extern tanh
- dasm_put(Dst, 4384, LJ_TISNUM, 1+1, LJ_TISNUM, 1+1, LJ_TISNUM);
- #line 2091 "vm_x86.dasc"
- //| math_extern2 pow
- //| math_extern2 atan2
- dasm_put(Dst, 4468, 2+1, LJ_TISNUM, LJ_TISNUM, 2+1, LJ_TISNUM);
- #line 2093 "vm_x86.dasc"
- //| math_extern2 fmod
- //|
- //|.ffunc_nnr math_ldexp; fscale; fpop1; jmp ->fff_resn
- dasm_put(Dst, 4558, LJ_TISNUM, 2+1, LJ_TISNUM, LJ_TISNUM, 2+1);
- #line 2096 "vm_x86.dasc"
- //|
- //|.ffunc_1 math_frexp
- //| mov RB, [BASE+4]
- //| cmp RB, LJ_TISNUM; jae ->fff_fallback
- //| mov PC, [BASE-4]
- //| mov RC, [BASE]
- //| mov [BASE-4], RB; mov [BASE-8], RC
- //| shl RB, 1; cmp RB, 0xffe00000; jae >3
- //| or RC, RB; jz >3
- //| mov RC, 1022
- //| cmp RB, 0x00200000; jb >4
- //|1:
- //| shr RB, 21; sub RB, RC // Extract and unbias exponent.
- dasm_put(Dst, 4654, LJ_TISNUM, LJ_TISNUM, 1+1, LJ_TISNUM);
- #line 2109 "vm_x86.dasc"
- //| cvtsi2sd xmm0, RB
- //| mov RB, [BASE-4]
- //| and RB, 0x800fffff // Mask off exponent.
- //| or RB, 0x3fe00000 // Put mantissa in range [0.5,1) or 0.
- //| mov [BASE-4], RB
- //|2:
- //| movsd qword [BASE], xmm0
- //| mov RD, 1+2
- //| jmp ->fff_res
- //|3: // Return +-0, +-Inf, NaN unmodified and an exponent of 0.
- //| xorps xmm0, xmm0; jmp <2
- //|4: // Handle denormals by multiplying with 2^54 and adjusting the bias.
- //| movsd xmm0, qword [BASE]
- //| sseconst_hi xmm1, RBa, 43500000 // 2^54.
- //| mulsd xmm0, xmm1
- //| movsd qword [BASE-8], xmm0
- //| mov RB, [BASE-4]; mov RC, 1076; shl RB, 1; jmp <1
- //|
- //|.ffunc_nsse math_modf
- //| mov RB, [BASE+4]
- //| mov PC, [BASE-4]
- //| shl RB, 1; cmp RB, 0xffe00000; je >4 // +-Inf?
- //| movaps xmm4, xmm0
- dasm_put(Dst, 4761, 1+2, (unsigned int)(U64x(43500000,00000000)), (unsigned int)((U64x(43500000,00000000))>>32), 1+1, LJ_TISNUM);
- #line 2132 "vm_x86.dasc"
- //| call ->vm_trunc_sse
- //| subsd xmm4, xmm0
- //|1:
- //| movsd qword [BASE-8], xmm0
- //| movsd qword [BASE], xmm4
- //| mov RC, [BASE-4]; mov RB, [BASE+4]
- //| xor RC, RB; js >3 // Need to adjust sign?
- //|2:
- //| mov RD, 1+2
- //| jmp ->fff_res
- //|3:
- //| xor RB, 0x80000000; mov [BASE+4], RB // Flip sign of fraction.
- //| jmp <2
- //|4:
- //| xorps xmm4, xmm4; jmp <1 // Return +-Inf and +-0.
- //|
- //|.macro math_minmax, name, cmovop, sseop
- //| .ffunc name
- //| mov RA, 2
- //| cmp dword [BASE+4], LJ_TISNUM
- //|.if DUALNUM
- //| jne >4
- //| mov RB, dword [BASE]
- //|1: // Handle integers.
- //| cmp RA, RD; jae ->fff_resi
- //| cmp dword [BASE+RA*8-4], LJ_TISNUM; jne >3
- //| cmp RB, dword [BASE+RA*8-8]
- //| cmovop RB, dword [BASE+RA*8-8]
- //| add RA, 1
- //| jmp <1
- //|3:
- //| ja ->fff_fallback
- //| // Convert intermediate result to number and continue below.
- //| cvtsi2sd xmm0, RB
- //| jmp >6
- //|4:
- //| ja ->fff_fallback
- //|.else
- //| jae ->fff_fallback
- //|.endif
- //|
- //| movsd xmm0, qword [BASE]
- //|5: // Handle numbers or integers.
- //| cmp RA, RD; jae ->fff_resxmm0
- //| cmp dword [BASE+RA*8-4], LJ_TISNUM
- //|.if DUALNUM
- //| jb >6
- //| ja ->fff_fallback
- //| cvtsi2sd xmm1, dword [BASE+RA*8-8]
- //| jmp >7
- //|.else
- //| jae ->fff_fallback
- //|.endif
- //|6:
- //| movsd xmm1, qword [BASE+RA*8-8]
- //|7:
- //| sseop xmm0, xmm1
- //| add RA, 1
- //| jmp <5
- //|.endmacro
- //|
- //| math_minmax math_min, cmovg, minsd
- dasm_put(Dst, 4905, 1+2, LJ_TISNUM);
- dasm_put(Dst, 4997, LJ_TISNUM, LJ_TISNUM);
- #line 2194 "vm_x86.dasc"
- //| math_minmax math_max, cmovl, maxsd
- dasm_put(Dst, 5078, LJ_TISNUM, LJ_TISNUM);
- #line 2195 "vm_x86.dasc"
- //|
- //|//-- String library -----------------------------------------------------
- //|
- //|.ffunc string_byte // Only handle the 1-arg case here.
- //| cmp NARGS:RD, 1+1; jne ->fff_fallback
- dasm_put(Dst, 5176, LJ_TISNUM);
- #line 2200 "vm_x86.dasc"
- //| cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback
- //| mov STR:RB, [BASE]
- //| mov PC, [BASE-4]
- //| cmp dword STR:RB->len, 1
- //| jb ->fff_res0 // Return no results for empty string.
- //| movzx RB, byte STR:RB[1]
- //|.if DUALNUM
- //| jmp ->fff_resi
- //|.else
- //| cvtsi2sd xmm0, RB; jmp ->fff_resxmm0
- //|.endif
- //|
- //|.ffunc string_char // Only handle the 1-arg case here.
- //| ffgccheck
- //| cmp NARGS:RD, 1+1; jne ->fff_fallback // *Exactly* 1 arg.
- dasm_put(Dst, 5262, 1+1, LJ_TSTR, Dt5(->len), Dt5([1]), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold));
- #line 2215 "vm_x86.dasc"
- //| cmp dword [BASE+4], LJ_TISNUM
- //|.if DUALNUM
- //| jne ->fff_fallback
- //| mov RB, dword [BASE]
- //| cmp RB, 255; ja ->fff_fallback
- //| mov TMP2, RB
- //|.else
- //| jae ->fff_fallback
- //| cvttsd2si RB, qword [BASE]
- //| cmp RB, 255; ja ->fff_fallback
- //| mov TMP2, RB
- //|.endif
- //|.if X64
- //| mov TMP3, 1
- //|.else
- //| mov ARG3, 1
- //|.endif
- //| lea RDa, TMP2 // Points to stack. Little-endian.
- //|->fff_newstr:
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //|.if X64
- //| mov CARG3d, TMP3 // Zero-extended to size_t.
- //| mov CARG2, RDa // May be 64 bit ptr to stack.
- //| mov CARG1d, L:RB
- //|.else
- //| mov ARG2, RD
- //| mov ARG1, L:RB
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_str_new // (lua_State *L, char *str, size_t l)
- //|->fff_resstr:
- //| // GCstr * returned in eax (RD).
- //| mov BASE, L:RB->base
- //| mov PC, [BASE-4]
- //| mov dword [BASE-4], LJ_TSTR
- //| mov [BASE-8], STR:RD
- //| jmp ->fff_res1
- //|
- //|.ffunc string_sub
- //| ffgccheck
- dasm_put(Dst, 5321, 1+1, LJ_TISNUM, Dt1(->base), Dt1(->base), LJ_TSTR, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold));
- #line 2256 "vm_x86.dasc"
- //| mov TMP2, -1
- //| cmp NARGS:RD, 1+2; jb ->fff_fallback
- //| jna >1
- //| cmp dword [BASE+20], LJ_TISNUM
- //|.if DUALNUM
- //| jne ->fff_fallback
- //| mov RB, dword [BASE+16]
- //| mov TMP2, RB
- //|.else
- //| jae ->fff_fallback
- //| cvttsd2si RB, qword [BASE+16]
- //| mov TMP2, RB
- //|.endif
- //|1:
- //| cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback
- //| cmp dword [BASE+12], LJ_TISNUM
- //|.if DUALNUM
- //| jne ->fff_fallback
- //|.else
- //| jae ->fff_fallback
- //|.endif
- //| mov STR:RB, [BASE]
- //| mov TMP3, STR:RB
- //| mov RB, STR:RB->len
- //|.if DUALNUM
- //| mov RA, dword [BASE+8]
- //|.else
- //| cvttsd2si RA, qword [BASE+8]
- //|.endif
- //| mov RC, TMP2
- //| cmp RB, RC // len < end? (unsigned compare)
- //| jb >5
- //|2:
- //| test RA, RA // start <= 0?
- dasm_put(Dst, 5433, 1+2, LJ_TISNUM, LJ_TSTR, LJ_TISNUM, Dt5(->len));
- #line 2290 "vm_x86.dasc"
- //| jle >7
- //|3:
- //| mov STR:RB, TMP3
- //| sub RC, RA // start > end?
- //| jl ->fff_emptystr
- //| lea RB, [STR:RB+RA+#STR-1]
- //| add RC, 1
- //|4:
- //|.if X64
- //| mov TMP3, RC
- //|.else
- //| mov ARG3, RC
- //|.endif
- //| mov RD, RB
- //| jmp ->fff_newstr
- //|
- //|5: // Negative end or overflow.
- //| jl >6
- //| lea RC, [RC+RB+1] // end = end+(len+1)
- //| jmp <2
- //|6: // Overflow.
- //| mov RC, RB // end = len
- //| jmp <2
- //|
- //|7: // Negative start or underflow.
- //| je >8
- //| add RA, RB // start = start+(len+1)
- dasm_put(Dst, 5523, sizeof(GCstr)-1);
- #line 2317 "vm_x86.dasc"
- //| add RA, 1
- //| jg <3 // start > 0?
- //|8: // Underflow.
- //| mov RA, 1 // start = 1
- //| jmp <3
- //|
- //|->fff_emptystr: // Range underflow.
- //| xor RC, RC // Zero length. Any ptr in RB is ok.
- //| jmp <4
- //|
- //|.macro ffstring_op, name
- //| .ffunc_1 string_ .. name
- //| ffgccheck
- //| cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback
- //| mov L:RB, SAVE_L
- //| lea SBUF:FCARG1, [DISPATCH+DISPATCH_GL(tmpbuf)]
- //| mov L:RB->base, BASE
- //| mov STR:FCARG2, [BASE] // Caveat: FCARG2 == BASE
- //| mov RC, SBUF:FCARG1->b
- //| mov SBUF:FCARG1->L, L:RB
- //| mov SBUF:FCARG1->p, RC
- //| mov SAVE_PC, PC
- //| call extern lj_buf_putstr_ .. name .. @8
- //| mov FCARG1, eax
- //| call extern lj_buf_tostr@4
- //| jmp ->fff_resstr
- //|.endmacro
- //|
- //|ffstring_op reverse
- dasm_put(Dst, 5590, 1+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), LJ_TSTR);
- #line 2346 "vm_x86.dasc"
- //|ffstring_op lower
- dasm_put(Dst, 5652, DISPATCH_GL(tmpbuf), Dt1(->base), DtE(->b), DtE(->L), DtE(->p), 1+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold));
- #line 2347 "vm_x86.dasc"
- //|ffstring_op upper
- dasm_put(Dst, 5724, LJ_TSTR, DISPATCH_GL(tmpbuf), Dt1(->base), DtE(->b), DtE(->L), DtE(->p), 1+1, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold));
- #line 2348 "vm_x86.dasc"
- //|
- //|//-- Bit library --------------------------------------------------------
- //|
- //|.define TOBIT_BIAS, 0x59c00000 // 2^52 + 2^51 (float, not double!).
- //|
- //|.macro .ffunc_bit, name, kind
- //| .ffunc_1 name
- //|.if kind == 2
- //| sseconst_tobit xmm1, RBa
- //|.endif
- //| cmp dword [BASE+4], LJ_TISNUM
- //|.if DUALNUM
- //| jne >1
- //| mov RB, dword [BASE]
- //|.if kind > 0
- //| jmp >2
- //|.else
- //| jmp ->fff_resbit
- //|.endif
- //|1:
- //| ja ->fff_fallback
- //|.else
- //| jae ->fff_fallback
- //|.endif
- //| movsd xmm0, qword [BASE]
- //|.if kind < 2
- //| sseconst_tobit xmm1, RBa
- //|.endif
- //| addsd xmm0, xmm1
- //| movd RB, xmm0
- //|2:
- //|.endmacro
- //|
- //|.ffunc_bit bit_tobit, 0
- dasm_put(Dst, 5801, LJ_TSTR, DISPATCH_GL(tmpbuf), Dt1(->base), DtE(->b), DtE(->L), DtE(->p), 1+1, LJ_TISNUM);
- #line 2382 "vm_x86.dasc"
- //| jmp ->fff_resbit
- //|
- //|.macro .ffunc_bit_op, name, ins
- //| .ffunc_bit name, 2
- //| mov TMP2, NARGS:RD // Save for fallback.
- //| lea RD, [BASE+NARGS:RD*8-16]
- //|1:
- //| cmp RD, BASE
- //| jbe ->fff_resbit
- //| cmp dword [RD+4], LJ_TISNUM
- //|.if DUALNUM
- //| jne >2
- //| ins RB, dword [RD]
- //| sub RD, 8
- //| jmp <1
- //|2:
- //| ja ->fff_fallback_bit_op
- //|.else
- //| jae ->fff_fallback_bit_op
- //|.endif
- //| movsd xmm0, qword [RD]
- //| addsd xmm0, xmm1
- //| movd RA, xmm0
- //| ins RB, RA
- //| sub RD, 8
- //| jmp <1
- //|.endmacro
- //|
- //|.ffunc_bit_op bit_band, and
- dasm_put(Dst, 5878, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32), 1+1, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32), LJ_TISNUM);
- #line 2411 "vm_x86.dasc"
- //|.ffunc_bit_op bit_bor, or
- dasm_put(Dst, 5952, LJ_TISNUM, 1+1, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- dasm_put(Dst, 6047, LJ_TISNUM, LJ_TISNUM);
- #line 2412 "vm_x86.dasc"
- //|.ffunc_bit_op bit_bxor, xor
- dasm_put(Dst, 6131, 1+1, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32), LJ_TISNUM);
- #line 2413 "vm_x86.dasc"
- //|
- //|.ffunc_bit bit_bswap, 1
- dasm_put(Dst, 6228, LJ_TISNUM, 1+1, LJ_TISNUM);
- #line 2415 "vm_x86.dasc"
- //| bswap RB
- //| jmp ->fff_resbit
- //|
- //|.ffunc_bit bit_bnot, 1
- dasm_put(Dst, 6303, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32), 1+1, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- #line 2419 "vm_x86.dasc"
- //| not RB
- //|.if DUALNUM
- //| jmp ->fff_resbit
- //|.else
- //|->fff_resbit:
- //| cvtsi2sd xmm0, RB
- //| jmp ->fff_resxmm0
- //|.endif
- //|
- //|->fff_fallback_bit_op:
- //| mov NARGS:RD, TMP2 // Restore for fallback
- //| jmp ->fff_fallback
- //|
- //|.macro .ffunc_bit_sh, name, ins
- //|.if DUALNUM
- //| .ffunc_bit name, 1
- //| // Note: no inline conversion from number for 2nd argument!
- //| cmp dword [BASE+12], LJ_TISNUM; jne ->fff_fallback
- //| mov RA, dword [BASE+8]
- //|.else
- //| .ffunc_nnsse name
- //| sseconst_tobit xmm2, RBa
- //| addsd xmm0, xmm2
- //| addsd xmm1, xmm2
- //| movd RB, xmm0
- //| movd RA, xmm1
- //|.endif
- //| ins RB, cl // Assumes RA is ecx.
- //| jmp ->fff_resbit
- //|.endmacro
- //|
- //|.ffunc_bit_sh bit_lshift, shl
- dasm_put(Dst, 6379, 1+1, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- #line 2451 "vm_x86.dasc"
- //|.ffunc_bit_sh bit_rshift, shr
- dasm_put(Dst, 6453, LJ_TISNUM, 1+1, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- #line 2452 "vm_x86.dasc"
- //|.ffunc_bit_sh bit_arshift, sar
- dasm_put(Dst, 6528, LJ_TISNUM, 1+1, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- #line 2453 "vm_x86.dasc"
- //|.ffunc_bit_sh bit_rol, rol
- dasm_put(Dst, 6604, LJ_TISNUM, 1+1, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- #line 2454 "vm_x86.dasc"
- //|.ffunc_bit_sh bit_ror, ror
- dasm_put(Dst, 6680, LJ_TISNUM, 1+1, LJ_TISNUM, (unsigned int)(U64x(43380000,00000000)), (unsigned int)((U64x(43380000,00000000))>>32));
- #line 2455 "vm_x86.dasc"
- //|
- //|//-----------------------------------------------------------------------
- //|
- //|->fff_fallback_2:
- //| mov NARGS:RD, 1+2 // Other args are ignored, anyway.
- //| jmp ->fff_fallback
- //|->fff_fallback_1:
- //| mov NARGS:RD, 1+1 // Other args are ignored, anyway.
- //|->fff_fallback: // Call fast function fallback handler.
- //| // BASE = new base, RD = nargs+1
- //| mov L:RB, SAVE_L
- //| mov PC, [BASE-4] // Fallback may overwrite PC.
- //| mov SAVE_PC, PC // Redundant (but a defined value).
- //| mov L:RB->base, BASE
- //| lea RD, [BASE+NARGS:RD*8-8]
- //| lea RA, [RD+8*LUA_MINSTACK] // Ensure enough space for handler.
- //| mov L:RB->top, RD
- //| mov CFUNC:RD, [BASE-8]
- //| cmp RA, L:RB->maxstack
- //| ja >5 // Need to grow stack.
- //|.if X64
- //| mov CARG1d, L:RB
- //|.else
- //| mov ARG1, L:RB
- //|.endif
- //| call aword CFUNC:RD->f // (lua_State *L)
- //| mov BASE, L:RB->base
- dasm_put(Dst, 6755, LJ_TISNUM, 1+2, 1+1, Dt1(->base), 8*LUA_MINSTACK, Dt1(->top), Dt1(->maxstack), Dt8(->f));
- #line 2482 "vm_x86.dasc"
- //| // Either throws an error, or recovers and returns -1, 0 or nresults+1.
- //| test RD, RD; jg ->fff_res // Returned nresults+1?
- //|1:
- //| mov RA, L:RB->top
- //| sub RA, BASE
- //| shr RA, 3
- //| test RD, RD
- //| lea NARGS:RD, [RA+1]
- //| mov LFUNC:RB, [BASE-8]
- //| jne ->vm_call_tail // Returned -1?
- //| ins_callt // Returned 0: retry fast path.
- //|
- //|// Reconstruct previous base for vmeta_call during tailcall.
- //|->vm_call_tail:
- //| mov RA, BASE
- //| test PC, FRAME_TYPE
- //| jnz >3
- //| movzx RB, PC_RA
- //| not RBa // Note: ~RB = -(RB+1)
- //| lea BASE, [BASE+RB*8] // base = base - (RB+1)*8
- //| jmp ->vm_call_dispatch // Resolve again for tailcall.
- //|3:
- //| mov RB, PC
- //| and RB, -8
- //| sub BASE, RB
- //| jmp ->vm_call_dispatch // Resolve again for tailcall.
- //|
- //|5: // Grow stack for fallback handler.
- //| mov FCARG2, LUA_MINSTACK
- //| mov FCARG1, L:RB
- //| call extern lj_state_growstack@8 // (lua_State *L, int n)
- //| mov BASE, L:RB->base
- //| xor RD, RD // Simulate a return 0.
- dasm_put(Dst, 6848, Dt1(->base), Dt1(->top), Dt7(->pc), FRAME_TYPE, LUA_MINSTACK, Dt1(->base));
- #line 2515 "vm_x86.dasc"
- //| jmp <1 // Dumb retry (goes through ff first).
- //|
- //|->fff_gcstep: // Call GC step function.
- //| // BASE = new base, RD = nargs+1
- //| pop RBa // Must keep stack at same level.
- //| mov TMPa, RBa // Save return address
- //| mov L:RB, SAVE_L
- //| mov SAVE_PC, PC // Redundant (but a defined value).
- //| mov L:RB->base, BASE
- //| lea RD, [BASE+NARGS:RD*8-8]
- //| mov FCARG1, L:RB
- //| mov L:RB->top, RD
- //| call extern lj_gc_step@4 // (lua_State *L)
- //| mov BASE, L:RB->base
- //| mov RD, L:RB->top
- //| sub RD, BASE
- //| shr RD, 3
- //| add NARGS:RD, 1
- //| mov RBa, TMPa
- //| push RBa // Restore return address.
- //| ret
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Special dispatch targets -------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|->vm_record: // Dispatch target for recording phase.
- //|.if JIT
- //| movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)]
- //| test RDL, HOOK_VMEVENT // No recording while in vmevent.
- //| jnz >5
- //| // Decrement the hookcount for consistency, but always do the call.
- //| test RDL, HOOK_ACTIVE
- //| jnz >1
- //| test RDL, LUA_MASKLINE|LUA_MASKCOUNT
- //| jz >1
- //| dec dword [DISPATCH+DISPATCH_GL(hookcount)]
- //| jmp >1
- //|.endif
- //|
- //|->vm_rethook: // Dispatch target for return hooks.
- //| movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)]
- dasm_put(Dst, 6961, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_GL(hookmask), HOOK_VMEVENT, HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount));
- #line 2557 "vm_x86.dasc"
- //| test RDL, HOOK_ACTIVE // Hook already active?
- //| jnz >5
- //| jmp >1
- //|
- //|->vm_inshook: // Dispatch target for instr/line hooks.
- //| movzx RD, byte [DISPATCH+DISPATCH_GL(hookmask)]
- //| test RDL, HOOK_ACTIVE // Hook already active?
- //| jnz >5
- //|
- //| test RDL, LUA_MASKLINE|LUA_MASKCOUNT
- //| jz >5
- //| dec dword [DISPATCH+DISPATCH_GL(hookcount)]
- //| jz >1
- //| test RDL, LUA_MASKLINE
- //| jz >5
- //|1:
- //| mov L:RB, SAVE_L
- dasm_put(Dst, 7059, DISPATCH_GL(hookmask), HOOK_ACTIVE, DISPATCH_GL(hookmask), HOOK_ACTIVE, LUA_MASKLINE|LUA_MASKCOUNT, DISPATCH_GL(hookcount), LUA_MASKLINE);
- #line 2574 "vm_x86.dasc"
- //| mov L:RB->base, BASE
- //| mov FCARG2, PC // Caveat: FCARG2 == BASE
- //| mov FCARG1, L:RB
- //| // SAVE_PC must hold the _previous_ PC. The callee updates it with PC.
- //| call extern lj_dispatch_ins@8 // (lua_State *L, const BCIns *pc)
- //|3:
- //| mov BASE, L:RB->base
- //|4:
- //| movzx RA, PC_RA
- //|5:
- //| movzx OP, PC_OP
- //| movzx RD, PC_RD
- //|.if X64
- //| jmp aword [DISPATCH+OP*8+GG_DISP2STATIC] // Re-dispatch to static ins.
- //|.else
- //| jmp aword [DISPATCH+OP*4+GG_DISP2STATIC] // Re-dispatch to static ins.
- //|.endif
- //|
- //|->cont_hook: // Continue from hook yield.
- //| add PC, 4
- //| mov RA, [RB-24]
- //| mov MULTRES, RA // Restore MULTRES for *M ins.
- //| jmp <4
- //|
- //|->vm_hotloop: // Hot loop counter underflow.
- //|.if JIT
- //| mov LFUNC:RB, [BASE-8] // Same as curr_topL(L).
- //| mov RB, LFUNC:RB->pc
- //| movzx RD, byte [RB+PC2PROTO(framesize)]
- //| lea RD, [BASE+RD*8]
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov L:RB->top, RD
- //| mov FCARG2, PC
- //| lea FCARG1, [DISPATCH+GG_DISP2J]
- //| mov aword [DISPATCH+DISPATCH_J(L)], L:RBa
- //| mov SAVE_PC, PC
- //| call extern lj_trace_hot@8 // (jit_State *J, const BCIns *pc)
- //| jmp <3
- //|.endif
- //|
- //|->vm_callhook: // Dispatch target for call hooks.
- //| mov SAVE_PC, PC
- //|.if JIT
- //| jmp >1
- //|.endif
- //|
- //|->vm_hotcall: // Hot call counter underflow.
- //|.if JIT
- //| mov SAVE_PC, PC
- dasm_put(Dst, 7111, Dt1(->base), Dt1(->base), GG_DISP2STATIC, Dt7(->pc), PC2PROTO(framesize), Dt1(->base), Dt1(->top), GG_DISP2J, DISPATCH_J(L));
- #line 2624 "vm_x86.dasc"
- //| or PC, 1 // Marker for hot call.
- //|1:
- //|.endif
- //| lea RD, [BASE+NARGS:RD*8-8]
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov L:RB->top, RD
- //| mov FCARG2, PC
- //| mov FCARG1, L:RB
- //| call extern lj_dispatch_call@8 // (lua_State *L, const BCIns *pc)
- //| // ASMFunction returned in eax/rax (RDa).
- //| mov SAVE_PC, 0 // Invalidate for subsequent line hook.
- //|.if JIT
- //| and PC, -2
- //|.endif
- //| mov BASE, L:RB->base
- //| mov RAa, RDa
- //| mov RD, L:RB->top
- //| sub RD, BASE
- //| mov RBa, RAa
- //| movzx RA, PC_RA
- //| shr RD, 3
- //| add NARGS:RD, 1
- //| jmp RBa
- //|
- //|->cont_stitch: // Trace stitching.
- //|.if JIT
- //| // BASE = base, RC = result, RB = mbase
- //| mov RA, [RB-24] // Save previous trace number.
- //| mov TMP1, RA
- //| mov TMP3, DISPATCH // Need one more register.
- //| mov DISPATCH, MULTRES
- //| movzx RA, PC_RA
- //| lea RA, [BASE+RA*8] // Call base.
- //| sub DISPATCH, 1
- //| jz >2
- //|1: // Move results down.
- //|.if X64
- //| mov RBa, [RC]
- //| mov [RA], RBa
- //|.else
- //| mov RB, [RC]
- //| mov [RA], RB
- //| mov RB, [RC+4]
- //| mov [RA+4], RB
- //|.endif
- //| add RC, 8
- //| add RA, 8
- //| sub DISPATCH, 1
- //| jnz <1
- //|2:
- //| movzx RC, PC_RA
- //| movzx RB, PC_RB
- //| add RC, RB
- //| lea RC, [BASE+RC*8-8]
- //|3:
- //| cmp RC, RA
- //| ja >9 // More results wanted?
- //|
- //| mov DISPATCH, TMP3
- //| mov RB, TMP1 // Get previous trace number.
- //| mov RA, [DISPATCH+DISPATCH_J(trace)]
- //| mov TRACE:RD, [RA+RB*4]
- //| test TRACE:RD, TRACE:RD
- //| jz ->cont_nop
- //| movzx RD, word TRACE:RD->link
- //| cmp RD, RB
- //| je ->cont_nop // Blacklisted.
- //| test RD, RD
- dasm_put(Dst, 7236, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_J(trace), DtD(->link));
- #line 2693 "vm_x86.dasc"
- //| jne =>BC_JLOOP // Jump to stitched trace.
- //|
- //| // Stitch a new trace to the previous trace.
- //| mov [DISPATCH+DISPATCH_J(exitno)], RB
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov FCARG2, PC
- //| lea FCARG1, [DISPATCH+GG_DISP2J]
- //| mov aword [DISPATCH+DISPATCH_J(L)], L:RBa
- //| call extern lj_dispatch_stitch@8 // (jit_State *J, const BCIns *pc)
- //| mov BASE, L:RB->base
- //| jmp ->cont_nop
- //|
- //|9: // Fill up results with nil.
- //| mov dword [RA+4], LJ_TNIL
- //| add RA, 8
- //| jmp <3
- //|.endif
- //|
- //|->vm_profhook: // Dispatch target for profiler hook.
- dasm_put(Dst, 7426, BC_JLOOP, DISPATCH_J(exitno), Dt1(->base), GG_DISP2J, DISPATCH_J(L), Dt1(->base), LJ_TNIL);
- #line 2713 "vm_x86.dasc"
- #if LJ_HASPROFILE
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov FCARG2, PC // Caveat: FCARG2 == BASE
- //| mov FCARG1, L:RB
- //| call extern lj_dispatch_profile@8 // (lua_State *L, const BCIns *pc)
- //| mov BASE, L:RB->base
- //| // HOOK_PROFILE is off again, so re-dispatch to dynamic instruction.
- //| sub PC, 4
- //| jmp ->cont_nop
- dasm_put(Dst, 7479, Dt1(->base), Dt1(->base));
- #line 2723 "vm_x86.dasc"
- #endif
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Trace exit handler -------------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|// Called from an exit stub with the exit number on the stack.
- //|// The 16 bit exit number is stored with two (sign-extended) push imm8.
- //|->vm_exit_handler:
- //|.if JIT
- //|.if X64
- //| push r13; push r12
- //| push r11; push r10; push r9; push r8
- //| push rdi; push rsi; push rbp; lea rbp, [rsp+88]; push rbp
- //| push rbx; push rdx; push rcx; push rax
- //| movzx RC, byte [rbp-8] // Reconstruct exit number.
- //| mov RCH, byte [rbp-16]
- //| mov [rbp-8], r15; mov [rbp-16], r14
- //|.else
- //| push ebp; lea ebp, [esp+12]; push ebp
- //| push ebx; push edx; push ecx; push eax
- //| movzx RC, byte [ebp-4] // Reconstruct exit number.
- //| mov RCH, byte [ebp-8]
- //| mov [ebp-4], edi; mov [ebp-8], esi
- //|.endif
- //| // Caveat: DISPATCH is ebx.
- //| mov DISPATCH, [ebp]
- //| mov RA, [DISPATCH+DISPATCH_GL(vmstate)] // Get trace number.
- //| set_vmstate EXIT
- //| mov [DISPATCH+DISPATCH_J(exitno)], RC
- //| mov [DISPATCH+DISPATCH_J(parent)], RA
- //|.if X64
- //|.if X64WIN
- //| sub rsp, 16*8+4*8 // Room for SSE regs + save area.
- //|.else
- //| sub rsp, 16*8 // Room for SSE regs.
- //|.endif
- //| add rbp, -128
- //| movsd qword [rbp-8], xmm15; movsd qword [rbp-16], xmm14
- //| movsd qword [rbp-24], xmm13; movsd qword [rbp-32], xmm12
- //| movsd qword [rbp-40], xmm11; movsd qword [rbp-48], xmm10
- //| movsd qword [rbp-56], xmm9; movsd qword [rbp-64], xmm8
- //| movsd qword [rbp-72], xmm7; movsd qword [rbp-80], xmm6
- //| movsd qword [rbp-88], xmm5; movsd qword [rbp-96], xmm4
- //| movsd qword [rbp-104], xmm3; movsd qword [rbp-112], xmm2
- //| movsd qword [rbp-120], xmm1; movsd qword [rbp-128], xmm0
- //|.else
- //| sub esp, 8*8+16 // Room for SSE regs + args.
- //| movsd qword [ebp-40], xmm7; movsd qword [ebp-48], xmm6
- //| movsd qword [ebp-56], xmm5; movsd qword [ebp-64], xmm4
- //| movsd qword [ebp-72], xmm3; movsd qword [ebp-80], xmm2
- //| movsd qword [ebp-88], xmm1; movsd qword [ebp-96], xmm0
- //|.endif
- //| // Caveat: RB is ebp.
- //| mov L:RB, [DISPATCH+DISPATCH_GL(cur_L)]
- //| mov BASE, [DISPATCH+DISPATCH_GL(jit_base)]
- //| mov aword [DISPATCH+DISPATCH_J(L)], L:RBa
- //| mov L:RB->base, BASE
- //|.if X64WIN
- //| lea CARG2, [rsp+4*8]
- //|.elif X64
- //| mov CARG2, rsp
- //|.else
- //| lea FCARG2, [esp+16]
- //|.endif
- //| lea FCARG1, [DISPATCH+GG_DISP2J]
- //| mov dword [DISPATCH+DISPATCH_GL(jit_base)], 0
- //| call extern lj_trace_exit@8 // (jit_State *J, ExitState *ex)
- //| // MULTRES or negated error code returned in eax (RD).
- //| mov RAa, L:RB->cframe
- //| and RAa, CFRAME_RAWMASK
- //|.if X64WIN
- //| // Reposition stack later.
- //|.elif X64
- //| mov rsp, RAa // Reposition stack to C frame.
- //|.else
- //| mov esp, RAa // Reposition stack to C frame.
- //|.endif
- //| mov [RAa+CFRAME_OFS_L], L:RB // Set SAVE_L (on-trace resume/yield).
- //| mov BASE, L:RB->base
- //| mov PC, [RAa+CFRAME_OFS_PC] // Get SAVE_PC.
- //|.if X64
- //| jmp >1
- //|.endif
- //|.endif
- //|->vm_exit_interp:
- //| // RD = MULTRES or negated error code, BASE, PC and DISPATCH set.
- //|.if JIT
- //|.if X64
- //| // Restore additional callee-save registers only used in compiled code.
- //|.if X64WIN
- //| lea RAa, [rsp+9*16+4*8]
- //|1:
- //| movdqa xmm15, [RAa-9*16]
- //| movdqa xmm14, [RAa-8*16]
- //| movdqa xmm13, [RAa-7*16]
- //| movdqa xmm12, [RAa-6*16]
- //| movdqa xmm11, [RAa-5*16]
- //| movdqa xmm10, [RAa-4*16]
- //| movdqa xmm9, [RAa-3*16]
- //| movdqa xmm8, [RAa-2*16]
- //| movdqa xmm7, [RAa-1*16]
- //| mov rsp, RAa // Reposition stack to C frame.
- //| movdqa xmm6, [RAa]
- //| mov r15, CSAVE_3
- //| mov r14, CSAVE_4
- //|.else
- //| add rsp, 16 // Reposition stack to C frame.
- dasm_put(Dst, 7507, DISPATCH_GL(vmstate), DISPATCH_GL(vmstate), ~LJ_VMST_EXIT, DISPATCH_J(exitno), DISPATCH_J(parent), 16*8, DISPATCH_GL(cur_L), DISPATCH_GL(jit_base), DISPATCH_J(L), Dt1(->base), GG_DISP2J, DISPATCH_GL(jit_base), Dt1(->cframe), CFRAME_RAWMASK, CFRAME_OFS_L, Dt1(->base), CFRAME_OFS_PC);
- #line 2831 "vm_x86.dasc"
- //|1:
- //|.endif
- //| mov r13, TMPa
- //| mov r12, TMPQ
- //|.endif
- dasm_put(Dst, 7750);
- #line 2836 "vm_x86.dasc"
- #ifdef LUA_USE_TRACE_LOGS
- //|.if X64
- //| mov FCARG1, SAVE_L
- //| mov L:FCARG1->base, BASE
- //| mov RB, RD // Save RD
- //| mov TMP1, PC // Save PC
- //| mov CARG3d, PC // CARG3d == BASE
- //| mov FCARG2, dword [DISPATCH+DISPATCH_GL(vmstate)]
- //| call extern lj_log_trace_direct_exit@8
- //| mov PC, TMP1
- //| mov RD, RB
- //| mov RB, SAVE_L
- //| mov BASE, L:RB->base
- //|.endif
- dasm_put(Dst, 7766, Dt1(->base), DISPATCH_GL(vmstate), Dt1(->base));
- #line 2850 "vm_x86.dasc"
- #endif
- //| test RD, RD; js >9 // Check for error from exit.
- //| mov L:RB, SAVE_L
- //| mov MULTRES, RD
- //| mov LFUNC:KBASE, [BASE-8]
- //| mov KBASE, LFUNC:KBASE->pc
- //| mov KBASE, [KBASE+PC2PROTO(k)]
- //| mov L:RB->base, BASE
- //| mov dword [DISPATCH+DISPATCH_GL(jit_base)], 0
- //| set_vmstate INTERP
- //| // Modified copy of ins_next which handles function header dispatch, too.
- //| mov RC, [PC]
- //| movzx RA, RCH
- //| movzx OP, RCL
- //| add PC, 4
- //| shr RC, 16
- //| cmp OP, BC_FUNCF // Function header?
- //| jb >3
- //| cmp OP, BC_FUNCC+2 // Fast function?
- //| jae >4
- //|2:
- //| mov RC, MULTRES // RC/RD holds nres+1.
- //|3:
- //|.if X64
- //| jmp aword [DISPATCH+OP*8]
- //|.else
- //| jmp aword [DISPATCH+OP*4]
- //|.endif
- //|
- //|4: // Check frame below fast function.
- //| mov RC, [BASE-4]
- //| test RC, FRAME_TYPE
- //| jnz <2 // Trace stitching continuation?
- //| // Otherwise set KBASE for Lua function below fast function.
- //| movzx RC, byte [RC-3]
- dasm_put(Dst, 7801, Dt7(->pc), PC2PROTO(k), Dt1(->base), DISPATCH_GL(jit_base), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, BC_FUNCF, BC_FUNCC+2, FRAME_TYPE);
- #line 2885 "vm_x86.dasc"
- //| not RCa
- //| mov LFUNC:KBASE, [BASE+RC*8-8]
- //| mov KBASE, LFUNC:KBASE->pc
- //| mov KBASE, [KBASE+PC2PROTO(k)]
- //| jmp <2
- //|
- //|9: // Rethrow error from the right C frame.
- //| neg RD
- //| mov FCARG1, L:RB
- //| mov FCARG2, RD
- //| call extern lj_err_throw@8 // (lua_State *L, int errcode)
- //|.endif
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Math helper functions ----------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|// FP value rounding. Called by math.floor/math.ceil fast functions
- //|// and from JIT code. arg/ret is xmm0. xmm0-xmm3 and RD (eax) modified.
- //|.macro vm_round, name, mode, cond
- //|->name:
- //|.if not X64 and cond
- //| movsd xmm0, qword [esp+4]
- //| call ->name .. _sse
- //| movsd qword [esp+4], xmm0 // Overwrite callee-owned arg.
- //| fld qword [esp+4]
- //| ret
- //|.endif
- //|
- //|->name .. _sse:
- //| sseconst_abs xmm2, RDa
- //| sseconst_2p52 xmm3, RDa
- //| movaps xmm1, xmm0
- //| andpd xmm1, xmm2 // |x|
- //| ucomisd xmm3, xmm1 // No truncation if 2^52 <= |x|.
- //| jbe >1
- //| andnpd xmm2, xmm0 // Isolate sign bit.
- //|.if mode == 2 // trunc(x)?
- //| movaps xmm0, xmm1
- //| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
- //| subsd xmm1, xmm3
- //| sseconst_1 xmm3, RDa
- //| cmpsd xmm0, xmm1, 1 // |x| < result?
- //| andpd xmm0, xmm3
- //| subsd xmm1, xmm0 // If yes, subtract -1.
- //| orpd xmm1, xmm2 // Merge sign bit back in.
- //|.else
- //| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
- //| subsd xmm1, xmm3
- //| orpd xmm1, xmm2 // Merge sign bit back in.
- //| .if mode == 1 // ceil(x)?
- //| sseconst_m1 xmm2, RDa // Must subtract -1 to preserve -0.
- //| cmpsd xmm0, xmm1, 6 // x > result?
- //| .else // floor(x)?
- //| sseconst_1 xmm2, RDa
- //| cmpsd xmm0, xmm1, 1 // x < result?
- //| .endif
- //| andpd xmm0, xmm2
- //| subsd xmm1, xmm0 // If yes, subtract +-1.
- //|.endif
- //| movaps xmm0, xmm1
- //|1:
- //| ret
- //|.endmacro
- //|
- //| vm_round vm_floor, 0, 1
- //| vm_round vm_ceil, 1, JIT
- dasm_put(Dst, 7901, Dt7(->pc), PC2PROTO(k), (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32));
- #line 2952 "vm_x86.dasc"
- //| vm_round vm_trunc, 2, JIT
- //|
- //|// FP modulo x%y. Called by BC_MOD* and vm_arith.
- //|->vm_mod:
- //|// Args in xmm0/xmm1, return value in xmm0.
- //|// Caveat: xmm0-xmm5 and RC (eax) modified!
- //| movaps xmm5, xmm0
- //| divsd xmm0, xmm1
- //| sseconst_abs xmm2, RDa
- dasm_put(Dst, 8036, (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(bff00000,00000000)), (unsigned int)((U64x(bff00000,00000000))>>32), (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32), (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(7fffffff,ffffffff)), (unsigned int)((U64x(7fffffff,ffffffff))>>32));
- #line 2961 "vm_x86.dasc"
- //| sseconst_2p52 xmm3, RDa
- //| movaps xmm4, xmm0
- //| andpd xmm4, xmm2 // |x/y|
- //| ucomisd xmm3, xmm4 // No truncation if 2^52 <= |x/y|.
- //| jbe >1
- //| andnpd xmm2, xmm0 // Isolate sign bit.
- //| addsd xmm4, xmm3 // (|x/y| + 2^52) - 2^52
- //| subsd xmm4, xmm3
- //| orpd xmm4, xmm2 // Merge sign bit back in.
- //| sseconst_1 xmm2, RDa
- //| cmpsd xmm0, xmm4, 1 // x/y < result?
- //| andpd xmm0, xmm2
- //| subsd xmm4, xmm0 // If yes, subtract 1.0.
- //| movaps xmm0, xmm5
- //| mulsd xmm1, xmm4
- //| subsd xmm0, xmm1
- //| ret
- //|1:
- //| mulsd xmm1, xmm0
- //| movaps xmm0, xmm5
- //| subsd xmm0, xmm1
- //| ret
- //|
- //|// Args in xmm0/eax. Ret in xmm0. xmm0-xmm1 and eax modified.
- //|->vm_powi_sse:
- //| cmp eax, 1; jle >6 // i<=1?
- //| // Now 1 < (unsigned)i <= 0x80000000.
- //|1: // Handle leading zeros.
- //| test eax, 1; jnz >2
- //| mulsd xmm0, xmm0
- //| shr eax, 1
- //| jmp <1
- //|2:
- //| shr eax, 1; jz >5
- //| movaps xmm1, xmm0
- //|3: // Handle trailing bits.
- //| mulsd xmm0, xmm0
- //| shr eax, 1; jz >4
- //| jnc <3
- dasm_put(Dst, 8216, (unsigned int)(U64x(43300000,00000000)), (unsigned int)((U64x(43300000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32));
- #line 3000 "vm_x86.dasc"
- //| mulsd xmm1, xmm0
- //| jmp <3
- //|4:
- //| mulsd xmm0, xmm1
- //|5:
- //| ret
- //|6:
- //| je <5 // x^1 ==> x
- //| jb >7 // x^0 ==> 1
- //| neg eax
- //| call <1
- //| sseconst_1 xmm1, RDa
- //| divsd xmm1, xmm0
- //| movaps xmm0, xmm1
- //| ret
- //|7:
- //| sseconst_1 xmm0, RDa
- //| ret
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Miscellaneous functions --------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|// int lj_vm_cpuid(uint32_t f, uint32_t res[4])
- //|->vm_cpuid:
- //|.if X64
- //| mov eax, CARG1d
- //| .if X64WIN; push rsi; mov rsi, CARG2; .endif
- //| push rbx
- //| cpuid
- //| mov [rsi], eax
- //| mov [rsi+4], ebx
- //| mov [rsi+8], ecx
- //| mov [rsi+12], edx
- //| pop rbx
- //| .if X64WIN; pop rsi; .endif
- //| ret
- //|.else
- //| pushfd
- //| pop edx
- //| mov ecx, edx
- //| xor edx, 0x00200000 // Toggle ID bit in flags.
- //| push edx
- //| popfd
- //| pushfd
- //| pop edx
- //| xor eax, eax // Zero means no features supported.
- //| cmp ecx, edx
- //| jz >1 // No ID toggle means no CPUID support.
- //| mov eax, [esp+4] // Argument 1 is function number.
- //| push edi
- //| push ebx
- //| cpuid
- //| mov edi, [esp+16] // Argument 2 is result area.
- //| mov [edi], eax
- //| mov [edi+4], ebx
- //| mov [edi+8], ecx
- //| mov [edi+12], edx
- //| pop ebx
- //| pop edi
- //|1:
- //| ret
- //|.endif
- //|
- //|//-----------------------------------------------------------------------
- //|//-- Assertions ---------------------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|->assert_bad_for_arg_type:
- dasm_put(Dst, 8374, (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32), (unsigned int)(U64x(3ff00000,00000000)), (unsigned int)((U64x(3ff00000,00000000))>>32));
- #line 3069 "vm_x86.dasc"
- #ifdef LUA_USE_ASSERT
- //| int3
- dasm_put(Dst, 8467);
- #line 3071 "vm_x86.dasc"
- #endif
- //| int3
- //|
- //|//-----------------------------------------------------------------------
- //|//-- FFI helper functions -----------------------------------------------
- //|//-----------------------------------------------------------------------
- //|
- //|// Handler for callback functions. Callback slot number in ah/al.
- //|->vm_ffi_callback:
- //|.if FFI
- //|.type CTSTATE, CTState, PC
- #define DtF(_V) (int)(ptrdiff_t)&(((CTState *)0)_V)
- #line 3082 "vm_x86.dasc"
- //|.if not X64
- //| sub esp, 16 // Leave room for SAVE_ERRF etc.
- //|.endif
- //| saveregs_ // ebp/rbp already saved. ebp now holds global_State *.
- //| lea DISPATCH, [ebp+GG_G2DISP]
- //| mov CTSTATE, GL:ebp->ctype_state
- //| movzx eax, ax
- //| mov CTSTATE->cb.slot, eax
- //|.if X64
- //| mov CTSTATE->cb.gpr[0], CARG1
- //| mov CTSTATE->cb.gpr[1], CARG2
- //| mov CTSTATE->cb.gpr[2], CARG3
- //| mov CTSTATE->cb.gpr[3], CARG4
- //| movsd qword CTSTATE->cb.fpr[0], xmm0
- //| movsd qword CTSTATE->cb.fpr[1], xmm1
- //| movsd qword CTSTATE->cb.fpr[2], xmm2
- //| movsd qword CTSTATE->cb.fpr[3], xmm3
- //|.if X64WIN
- //| lea rax, [rsp+CFRAME_SIZE+4*8]
- //|.else
- //| lea rax, [rsp+CFRAME_SIZE]
- //| mov CTSTATE->cb.gpr[4], CARG5
- //| mov CTSTATE->cb.gpr[5], CARG6
- //| movsd qword CTSTATE->cb.fpr[4], xmm4
- //| movsd qword CTSTATE->cb.fpr[5], xmm5
- //| movsd qword CTSTATE->cb.fpr[6], xmm6
- //| movsd qword CTSTATE->cb.fpr[7], xmm7
- //|.endif
- //| mov CTSTATE->cb.stack, rax
- //| mov CARG2, rsp
- dasm_put(Dst, 8469, GG_G2DISP, Dt2(->ctype_state), DtF(->cb.slot), DtF(->cb.gpr[0]), DtF(->cb.gpr[1]), DtF(->cb.gpr[2]), DtF(->cb.gpr[3]), DtF(->cb.fpr[0]), DtF(->cb.fpr[1]), DtF(->cb.fpr[2]), DtF(->cb.fpr[3]), CFRAME_SIZE, DtF(->cb.gpr[4]), DtF(->cb.gpr[5]), DtF(->cb.fpr[4]), DtF(->cb.fpr[5]), DtF(->cb.fpr[6]), DtF(->cb.fpr[7]), DtF(->cb.stack));
- #line 3112 "vm_x86.dasc"
- //|.else
- //| lea eax, [esp+CFRAME_SIZE+16]
- //| mov CTSTATE->cb.gpr[0], FCARG1
- //| mov CTSTATE->cb.gpr[1], FCARG2
- //| mov CTSTATE->cb.stack, eax
- //| mov FCARG1, [esp+CFRAME_SIZE+12] // Move around misplaced retaddr/ebp.
- //| mov FCARG2, [esp+CFRAME_SIZE+8]
- //| mov SAVE_RET, FCARG1
- //| mov SAVE_R4, FCARG2
- //| mov FCARG2, esp
- //|.endif
- //| mov SAVE_PC, CTSTATE // Any value outside of bytecode is ok.
- //| mov FCARG1, CTSTATE
- //| call extern lj_ccallback_enter@8 // (CTState *cts, void *cf)
- //| // lua_State * returned in eax (RD).
- //| set_vmstate INTERP
- //| mov BASE, L:RD->base
- //| mov RD, L:RD->top
- //| sub RD, BASE
- //| mov LFUNC:RB, [BASE-8]
- //| shr RD, 3
- //| add RD, 1
- //| ins_callt
- //|.endif
- //|
- //|->cont_ffi_callback: // Return from FFI callback.
- //|.if FFI
- //| mov L:RA, SAVE_L
- //| mov CTSTATE, [DISPATCH+DISPATCH_GL(ctype_state)]
- //| mov aword CTSTATE->L, L:RAa
- //| mov L:RA->base, BASE
- //| mov L:RA->top, RB
- //| mov FCARG1, CTSTATE
- //| mov FCARG2, RC
- //| call extern lj_ccallback_leave@8 // (CTState *cts, TValue *o)
- //|.if X64
- //| mov rax, CTSTATE->cb.gpr[0]
- //| movsd xmm0, qword CTSTATE->cb.fpr[0]
- //| jmp ->vm_leave_unw
- //|.else
- //| mov L:RB, SAVE_L
- //| mov eax, CTSTATE->cb.gpr[0]
- //| mov edx, CTSTATE->cb.gpr[1]
- //| cmp dword CTSTATE->cb.gpr[2], 1
- //| jb >7
- //| je >6
- //| fld qword CTSTATE->cb.fpr[0].d
- //| jmp >7
- //|6:
- //| fld dword CTSTATE->cb.fpr[0].f
- //|7:
- //| mov ecx, L:RB->top
- //| movzx ecx, word [ecx+6] // Get stack adjustment and copy up.
- //| mov SAVE_L, ecx // Must be one slot above SAVE_RET
- //| restoreregs
- //| pop ecx // Move return addr from SAVE_RET.
- //| add esp, [esp] // Adjust stack.
- //| add esp, 16
- //| push ecx
- //| ret
- //|.endif
- //|.endif
- //|
- //|->vm_ffi_call@4: // Call C function via FFI.
- //| // Caveat: needs special frame unwinding, see below.
- //|.if FFI
- //|.if X64
- //| .type CCSTATE, CCallState, rbx
- #define Dt10(_V) (int)(ptrdiff_t)&(((CCallState *)0)_V)
- #line 3180 "vm_x86.dasc"
- //| push rbp; mov rbp, rsp; push rbx; mov CCSTATE, CARG1
- //|.else
- //| .type CCSTATE, CCallState, ebx
- //| push ebp; mov ebp, esp; push ebx; mov CCSTATE, FCARG1
- //|.endif
- //|
- //| // Readjust stack.
- //|.if X64
- //| mov eax, CCSTATE->spadj
- //| sub rsp, rax
- //|.else
- //| sub esp, CCSTATE->spadj
- //|.if WIN
- //| mov CCSTATE->spadj, esp
- //|.endif
- //|.endif
- //|
- //| // Copy stack slots.
- //| movzx ecx, byte CCSTATE->nsp
- //| sub ecx, 1
- //| js >2
- //|1:
- //|.if X64
- //| mov rax, [CCSTATE+rcx*8+offsetof(CCallState, stack)]
- dasm_put(Dst, 8578, DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base), Dt1(->top), Dt7(->pc), DISPATCH_GL(ctype_state), DtF(->L), Dt1(->base), Dt1(->top), DtF(->cb.gpr[0]), DtF(->cb.fpr[0]), Dt10(->spadj), Dt10(->nsp));
- #line 3204 "vm_x86.dasc"
- //| mov [rsp+rcx*8+CCALL_SPS_EXTRA*8], rax
- //|.else
- //| mov eax, [CCSTATE+ecx*4+offsetof(CCallState, stack)]
- //| mov [esp+ecx*4], eax
- //|.endif
- //| sub ecx, 1
- //| jns <1
- //|2:
- //|
- //|.if X64
- //| movzx eax, byte CCSTATE->nfpr
- //| mov CARG1, CCSTATE->gpr[0]
- //| mov CARG2, CCSTATE->gpr[1]
- //| mov CARG3, CCSTATE->gpr[2]
- //| mov CARG4, CCSTATE->gpr[3]
- //|.if not X64WIN
- //| mov CARG5, CCSTATE->gpr[4]
- //| mov CARG6, CCSTATE->gpr[5]
- //|.endif
- //| test eax, eax; jz >5
- //| movaps xmm0, CCSTATE->fpr[0]
- //| movaps xmm1, CCSTATE->fpr[1]
- //| movaps xmm2, CCSTATE->fpr[2]
- //| movaps xmm3, CCSTATE->fpr[3]
- //|.if not X64WIN
- //| cmp eax, 4; jbe >5
- //| movaps xmm4, CCSTATE->fpr[4]
- dasm_put(Dst, 8709, offsetof(CCallState, stack), CCALL_SPS_EXTRA*8, Dt10(->nfpr), Dt10(->gpr[0]), Dt10(->gpr[1]), Dt10(->gpr[2]), Dt10(->gpr[3]), Dt10(->gpr[4]), Dt10(->gpr[5]), Dt10(->fpr[0]), Dt10(->fpr[1]), Dt10(->fpr[2]), Dt10(->fpr[3]));
- #line 3231 "vm_x86.dasc"
- //| movaps xmm5, CCSTATE->fpr[5]
- //| movaps xmm6, CCSTATE->fpr[6]
- //| movaps xmm7, CCSTATE->fpr[7]
- //|.endif
- //|5:
- //|.else
- //| mov FCARG1, CCSTATE->gpr[0]
- //| mov FCARG2, CCSTATE->gpr[1]
- //|.endif
- //|
- //| call aword CCSTATE->func
- //|
- //|.if X64
- //| mov CCSTATE->gpr[0], rax
- //| movaps CCSTATE->fpr[0], xmm0
- //|.if not X64WIN
- //| mov CCSTATE->gpr[1], rdx
- //| movaps CCSTATE->fpr[1], xmm1
- //|.endif
- //|.else
- //| mov CCSTATE->gpr[0], eax
- //| mov CCSTATE->gpr[1], edx
- //| cmp byte CCSTATE->resx87, 1
- //| jb >7
- //| je >6
- //| fstp qword CCSTATE->fpr[0].d[0]
- //| jmp >7
- //|6:
- //| fstp dword CCSTATE->fpr[0].f[0]
- //|7:
- //|.if WIN
- //| sub CCSTATE->spadj, esp
- //|.endif
- //|.endif
- //|
- //|.if X64
- //| mov rbx, [rbp-8]; leave; ret
- //|.else
- //| mov ebx, [ebp-4]; leave; ret
- //|.endif
- //|.endif
- //|// Note: vm_ffi_call must be the last function in this object file!
- //|
- //|//-----------------------------------------------------------------------
- dasm_put(Dst, 8790, Dt10(->fpr[4]), Dt10(->fpr[5]), Dt10(->fpr[6]), Dt10(->fpr[7]), Dt10(->func), Dt10(->gpr[0]), Dt10(->fpr[0]), Dt10(->gpr[1]), Dt10(->fpr[1]));
- #line 3275 "vm_x86.dasc"
- }
- /* Generate the code for a single instruction. */
- static void build_ins(BuildCtx *ctx, BCOp op, int defop)
- {
- int vk = 0;
- //|// Note: aligning all instructions does not pay off.
- //|=>defop:
- dasm_put(Dst, 8836, defop);
- #line 3283 "vm_x86.dasc"
- switch (op) {
- /* -- Comparison ops ---------------------------------------------------- */
- /* Remember: all ops branch for a true comparison, fall through otherwise. */
- //|.macro jmp_comp, lt, ge, le, gt, target
- //||switch (op) {
- //||case BC_ISLT:
- //| lt target
- //||break;
- //||case BC_ISGE:
- //| ge target
- //||break;
- //||case BC_ISLE:
- //| le target
- //||break;
- //||case BC_ISGT:
- //| gt target
- //||break;
- //||default: break; /* Shut up GCC. */
- //||}
- //|.endmacro
- case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
- //| // RA = src1, RD = src2, JMP with RD = target
- //| ins_AD
- //|.if DUALNUM
- //| checkint RA, >7
- //| checkint RD, >8
- //| mov RB, dword [BASE+RA*8]
- //| add PC, 4
- //| cmp RB, dword [BASE+RD*8]
- //| jmp_comp jge, jl, jg, jle, >9
- dasm_put(Dst, 8838, LJ_TISNUM, LJ_TISNUM);
- switch (op) {
- case BC_ISLT:
- dasm_put(Dst, 8868);
- break;
- case BC_ISGE:
- dasm_put(Dst, 8873);
- break;
- case BC_ISLE:
- dasm_put(Dst, 8878);
- break;
- case BC_ISGT:
- dasm_put(Dst, 8883);
- break;
- default: break; /* Shut up GCC. */
- }
- #line 3318 "vm_x86.dasc"
- //|6:
- //| movzx RD, PC_RD
- //| branchPC RD
- //|9:
- //| ins_next
- //|
- //|7: // RA is not an integer.
- //| ja ->vmeta_comp
- //| // RA is a number.
- //| cmp dword [BASE+RD*8+4], LJ_TISNUM; jb >1; jne ->vmeta_comp
- //| // RA is a number, RD is an integer.
- //| cvtsi2sd xmm0, dword [BASE+RD*8]
- //| jmp >2
- //|
- //|8: // RA is an integer, RD is not an integer.
- //| ja ->vmeta_comp
- //| // RA is an integer, RD is a number.
- //| cvtsi2sd xmm1, dword [BASE+RA*8]
- //| movsd xmm0, qword [BASE+RD*8]
- //| add PC, 4
- //| ucomisd xmm0, xmm1
- //| jmp_comp jbe, ja, jb, jae, <9
- dasm_put(Dst, 8888, -BCBIAS_J*4, LJ_TISNUM);
- switch (op) {
- case BC_ISLT:
- dasm_put(Dst, 8978);
- break;
- case BC_ISGE:
- dasm_put(Dst, 8983);
- break;
- case BC_ISLE:
- dasm_put(Dst, 8988);
- break;
- case BC_ISGT:
- dasm_put(Dst, 8993);
- break;
- default: break; /* Shut up GCC. */
- }
- #line 3340 "vm_x86.dasc"
- //| jmp <6
- //|.else
- //| checknum RA, ->vmeta_comp
- //| checknum RD, ->vmeta_comp
- //|.endif
- //|1:
- //| movsd xmm0, qword [BASE+RD*8]
- //|2:
- //| add PC, 4
- //| ucomisd xmm0, qword [BASE+RA*8]
- //|3:
- //| // Unordered: all of ZF CF PF set, ordered: PF clear.
- //| // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't.
- //|.if DUALNUM
- //| jmp_comp jbe, ja, jb, jae, <9
- dasm_put(Dst, 8998);
- switch (op) {
- case BC_ISLT:
- dasm_put(Dst, 8978);
- break;
- case BC_ISGE:
- dasm_put(Dst, 8983);
- break;
- case BC_ISLE:
- dasm_put(Dst, 8988);
- break;
- case BC_ISGT:
- dasm_put(Dst, 8993);
- break;
- default: break; /* Shut up GCC. */
- }
- #line 3355 "vm_x86.dasc"
- //| jmp <6
- //|.else
- //| jmp_comp jbe, ja, jb, jae, >1
- //| movzx RD, PC_RD
- //| branchPC RD
- //|1:
- //| ins_next
- //|.endif
- dasm_put(Dst, 9023);
- #line 3363 "vm_x86.dasc"
- break;
- case BC_ISEQV: case BC_ISNEV:
- vk = op == BC_ISEQV;
- //| ins_AD // RA = src1, RD = src2, JMP with RD = target
- //| mov RB, [BASE+RD*8+4]
- //| add PC, 4
- //|.if DUALNUM
- //| cmp RB, LJ_TISNUM; jne >7
- //| checkint RA, >8
- //| mov RB, dword [BASE+RD*8]
- //| cmp RB, dword [BASE+RA*8]
- dasm_put(Dst, 9028, LJ_TISNUM, LJ_TISNUM);
- #line 3375 "vm_x86.dasc"
- if (vk) {
- //| jne >9
- dasm_put(Dst, 9060);
- #line 3377 "vm_x86.dasc"
- } else {
- //| je >9
- dasm_put(Dst, 9065);
- #line 3379 "vm_x86.dasc"
- }
- //| movzx RD, PC_RD
- //| branchPC RD
- //|9:
- //| ins_next
- //|
- //|7: // RD is not an integer.
- //| ja >5
- //| // RD is a number.
- //| cmp dword [BASE+RA*8+4], LJ_TISNUM; jb >1; jne >5
- //| // RD is a number, RA is an integer.
- //| cvtsi2sd xmm0, dword [BASE+RA*8]
- //| jmp >2
- //|
- //|8: // RD is an integer, RA is not an integer.
- //| ja >5
- //| // RD is an integer, RA is a number.
- //| cvtsi2sd xmm0, dword [BASE+RD*8]
- //| ucomisd xmm0, qword [BASE+RA*8]
- //| jmp >4
- //|
- //|.else
- //| cmp RB, LJ_TISNUM; jae >5
- //| checknum RA, >5
- //|.endif
- //|1:
- //| movsd xmm0, qword [BASE+RA*8]
- //|2:
- //| ucomisd xmm0, qword [BASE+RD*8]
- //|4:
- dasm_put(Dst, 9070, -BCBIAS_J*4, LJ_TISNUM);
- #line 3409 "vm_x86.dasc"
- iseqne_fp:
- if (vk) {
- //| jp >2 // Unordered means not equal.
- //| jne >2
- dasm_put(Dst, 9171);
- #line 3413 "vm_x86.dasc"
- } else {
- //| jp >2 // Unordered means not equal.
- //| je >1
- dasm_put(Dst, 9180);
- #line 3416 "vm_x86.dasc"
- }
- iseqne_end:
- if (vk) {
- //|1: // EQ: Branch to the target.
- //| movzx RD, PC_RD
- //| branchPC RD
- //|2: // NE: Fallthrough to next instruction.
- //|.if not FFI
- //|3:
- //|.endif
- dasm_put(Dst, 9189, -BCBIAS_J*4);
- #line 3426 "vm_x86.dasc"
- } else {
- //|.if not FFI
- //|3:
- //|.endif
- //|2: // NE: Branch to the target.
- //| movzx RD, PC_RD
- //| branchPC RD
- //|1: // EQ: Fallthrough to next instruction.
- dasm_put(Dst, 9204, -BCBIAS_J*4);
- #line 3434 "vm_x86.dasc"
- }
- if (LJ_DUALNUM && (op == BC_ISEQV || op == BC_ISNEV ||
- op == BC_ISEQN || op == BC_ISNEN)) {
- //| jmp <9
- dasm_put(Dst, 9219);
- #line 3438 "vm_x86.dasc"
- } else {
- //| ins_next
- dasm_put(Dst, 9224);
- #line 3440 "vm_x86.dasc"
- }
- //|
- if (op == BC_ISEQV || op == BC_ISNEV) {
- //|5: // Either or both types are not numbers.
- //|.if FFI
- //| cmp RB, LJ_TCDATA; je ->vmeta_equal_cd
- //| checktp RA, LJ_TCDATA; je ->vmeta_equal_cd
- //|.endif
- //| checktp RA, RB // Compare types.
- //| jne <2 // Not the same type?
- //| cmp RB, LJ_TISPRI
- //| jae <1 // Same type and primitive type?
- //|
- //| // Same types and not a primitive type. Compare GCobj or pvalue.
- //| mov RA, [BASE+RA*8]
- //| mov RD, [BASE+RD*8]
- //| cmp RA, RD
- //| je <1 // Same GCobjs or pvalues?
- //| cmp RB, LJ_TISTABUD
- //| ja <2 // Different objects and not table/ud?
- //|.if X64
- //| cmp RB, LJ_TUDATA // And not 64 bit lightuserdata.
- //| jb <2
- //|.endif
- //|
- //| // Different tables or userdatas. Need to check __eq metamethod.
- //| // Field metatable must be at same offset for GCtab and GCudata!
- //| mov TAB:RB, TAB:RA->metatable
- dasm_put(Dst, 9245, LJ_TCDATA, LJ_TCDATA, LJ_TISPRI, LJ_TISTABUD, LJ_TUDATA);
- #line 3468 "vm_x86.dasc"
- //| test TAB:RB, TAB:RB
- //| jz <2 // No metatable?
- //| test byte TAB:RB->nomm, 1<<MM_eq
- //| jnz <2 // Or 'no __eq' flag set?
- dasm_put(Dst, 9310, Dt6(->metatable), Dt6(->nomm), 1<<MM_eq);
- #line 3472 "vm_x86.dasc"
- if (vk) {
- //| xor RB, RB // ne = 0
- dasm_put(Dst, 9330);
- #line 3474 "vm_x86.dasc"
- } else {
- //| mov RB, 1 // ne = 1
- dasm_put(Dst, 9334);
- #line 3476 "vm_x86.dasc"
- }
- //| jmp ->vmeta_equal // Handle __eq metamethod.
- dasm_put(Dst, 9340);
- #line 3478 "vm_x86.dasc"
- } else {
- //|.if FFI
- //|3:
- //| cmp RB, LJ_TCDATA
- dasm_put(Dst, 9345, LJ_TCDATA);
- #line 3482 "vm_x86.dasc"
- if (LJ_DUALNUM && vk) {
- //| jne <9
- dasm_put(Dst, 9352);
- #line 3484 "vm_x86.dasc"
- } else {
- //| jne <2
- dasm_put(Dst, 7896);
- #line 3486 "vm_x86.dasc"
- }
- //| jmp ->vmeta_equal_cd
- //|.endif
- dasm_put(Dst, 9357);
- #line 3489 "vm_x86.dasc"
- }
- break;
- case BC_ISEQS: case BC_ISNES:
- vk = op == BC_ISEQS;
- //| ins_AND // RA = src, RD = str const, JMP with RD = target
- //| mov RB, [BASE+RA*8+4]
- //| add PC, 4
- //| cmp RB, LJ_TSTR; jne >3
- //| mov RA, [BASE+RA*8]
- //| cmp RA, [KBASE+RD*4]
- dasm_put(Dst, 9362, LJ_TSTR);
- #line 3499 "vm_x86.dasc"
- iseqne_test:
- if (vk) {
- //| jne >2
- dasm_put(Dst, 3670);
- #line 3502 "vm_x86.dasc"
- } else {
- //| je >1
- dasm_put(Dst, 9184);
- #line 3504 "vm_x86.dasc"
- }
- goto iseqne_end;
- case BC_ISEQN: case BC_ISNEN:
- vk = op == BC_ISEQN;
- //| ins_AD // RA = src, RD = num const, JMP with RD = target
- //| mov RB, [BASE+RA*8+4]
- //| add PC, 4
- //|.if DUALNUM
- //| cmp RB, LJ_TISNUM; jne >7
- //| cmp dword [KBASE+RD*8+4], LJ_TISNUM; jne >8
- //| mov RB, dword [KBASE+RD*8]
- //| cmp RB, dword [BASE+RA*8]
- dasm_put(Dst, 9389, LJ_TISNUM, LJ_TISNUM);
- #line 3516 "vm_x86.dasc"
- if (vk) {
- //| jne >9
- dasm_put(Dst, 9060);
- #line 3518 "vm_x86.dasc"
- } else {
- //| je >9
- dasm_put(Dst, 9065);
- #line 3520 "vm_x86.dasc"
- }
- //| movzx RD, PC_RD
- //| branchPC RD
- //|9:
- //| ins_next
- //|
- //|7: // RA is not an integer.
- //| ja >3
- //| // RA is a number.
- //| cmp dword [KBASE+RD*8+4], LJ_TISNUM; jb >1
- //| // RA is a number, RD is an integer.
- //| cvtsi2sd xmm0, dword [KBASE+RD*8]
- //| jmp >2
- //|
- //|8: // RA is an integer, RD is a number.
- //| cvtsi2sd xmm0, dword [BASE+RA*8]
- //| ucomisd xmm0, qword [KBASE+RD*8]
- //| jmp >4
- //|.else
- //| cmp RB, LJ_TISNUM; jae >3
- //|.endif
- //|1:
- //| movsd xmm0, qword [KBASE+RD*8]
- //|2:
- //| ucomisd xmm0, qword [BASE+RA*8]
- //|4:
- dasm_put(Dst, 9423, -BCBIAS_J*4, LJ_TISNUM);
- #line 3546 "vm_x86.dasc"
- goto iseqne_fp;
- case BC_ISEQP: case BC_ISNEP:
- vk = op == BC_ISEQP;
- //| ins_AND // RA = src, RD = primitive type (~), JMP with RD = target
- //| mov RB, [BASE+RA*8+4]
- //| add PC, 4
- //| cmp RB, RD
- dasm_put(Dst, 9520);
- #line 3553 "vm_x86.dasc"
- if (!LJ_HASFFI) goto iseqne_test;
- if (vk) {
- //| jne >3
- //| movzx RD, PC_RD
- //| branchPC RD
- //|2:
- //| ins_next
- //|3:
- //| cmp RB, LJ_TCDATA; jne <2
- //| jmp ->vmeta_equal_cd
- dasm_put(Dst, 9534, -BCBIAS_J*4, LJ_TCDATA);
- #line 3563 "vm_x86.dasc"
- } else {
- //| je >2
- //| cmp RB, LJ_TCDATA; je ->vmeta_equal_cd
- //| movzx RD, PC_RD
- //| branchPC RD
- //|2:
- //| ins_next
- dasm_put(Dst, 9585, LJ_TCDATA, -BCBIAS_J*4);
- #line 3570 "vm_x86.dasc"
- }
- break;
- /* -- Unary test and copy ops ------------------------------------------- */
- case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
- //| ins_AD // RA = dst or unused, RD = src, JMP with RD = target
- //| mov RB, [BASE+RD*8+4]
- //| add PC, 4
- //| cmp RB, LJ_TISTRUECOND
- dasm_put(Dst, 9630, LJ_TISTRUECOND);
- #line 3580 "vm_x86.dasc"
- if (op == BC_IST || op == BC_ISTC) {
- //| jae >1
- dasm_put(Dst, 9642);
- #line 3582 "vm_x86.dasc"
- } else {
- //| jb >1
- dasm_put(Dst, 5428);
- #line 3584 "vm_x86.dasc"
- }
- if (op == BC_ISTC || op == BC_ISFC) {
- //| mov [BASE+RA*8+4], RB
- //| mov RB, [BASE+RD*8]
- //| mov [BASE+RA*8], RB
- dasm_put(Dst, 9647);
- #line 3589 "vm_x86.dasc"
- }
- //| movzx RD, PC_RD
- //| branchPC RD
- //|1: // Fallthrough to the next instruction.
- //| ins_next
- dasm_put(Dst, 9658, -BCBIAS_J*4);
- #line 3594 "vm_x86.dasc"
- break;
- case BC_ISTYPE:
- //| ins_AD // RA = src, RD = -type
- //| add RD, [BASE+RA*8+4]
- //| jne ->vmeta_istype
- //| ins_next
- dasm_put(Dst, 9691);
- #line 3601 "vm_x86.dasc"
- break;
- case BC_ISNUM:
- //| ins_AD // RA = src, RD = -(TISNUM-1)
- //| checknum RA, ->vmeta_istype
- //| ins_next
- dasm_put(Dst, 9720, LJ_TISNUM);
- #line 3606 "vm_x86.dasc"
- break;
- /* -- Unary ops --------------------------------------------------------- */
- case BC_MOV:
- //| ins_AD // RA = dst, RD = src
- //|.if X64
- //| mov RBa, [BASE+RD*8]
- //| mov [BASE+RA*8], RBa
- //|.else
- //| mov RB, [BASE+RD*8+4]
- //| mov RD, [BASE+RD*8]
- //| mov [BASE+RA*8+4], RB
- //| mov [BASE+RA*8], RD
- //|.endif
- //| ins_next_
- dasm_put(Dst, 9751);
- #line 3622 "vm_x86.dasc"
- break;
- case BC_NOT:
- //| ins_AD // RA = dst, RD = src
- //| xor RB, RB
- //| checktp RD, LJ_TISTRUECOND
- //| adc RB, LJ_TTRUE
- //| mov [BASE+RA*8+4], RB
- //| ins_next
- dasm_put(Dst, 9780, LJ_TISTRUECOND, LJ_TTRUE);
- #line 3630 "vm_x86.dasc"
- break;
- case BC_UNM:
- //| ins_AD // RA = dst, RD = src
- //|.if DUALNUM
- //| checkint RD, >5
- //| mov RB, [BASE+RD*8]
- //| neg RB
- //| jo >4
- //| mov dword [BASE+RA*8+4], LJ_TISNUM
- //| mov dword [BASE+RA*8], RB
- //|9:
- //| ins_next
- //|4:
- //| mov dword [BASE+RA*8+4], 0x41e00000 // 2^31.
- //| mov dword [BASE+RA*8], 0
- //| jmp <9
- //|5:
- //| ja ->vmeta_unm
- //|.else
- //| checknum RD, ->vmeta_unm
- //|.endif
- //| movsd xmm0, qword [BASE+RD*8]
- //| sseconst_sign xmm1, RDa
- //| xorps xmm0, xmm1
- //| movsd qword [BASE+RA*8], xmm0
- //|.if DUALNUM
- //| jmp <9
- //|.else
- //| ins_next
- //|.endif
- dasm_put(Dst, 9817, LJ_TISNUM, LJ_TISNUM, (unsigned int)(U64x(80000000,00000000)), (unsigned int)((U64x(80000000,00000000))>>32));
- #line 3660 "vm_x86.dasc"
- break;
- case BC_LEN:
- //| ins_AD // RA = dst, RD = src
- //| checkstr RD, >2
- //| mov STR:RD, [BASE+RD*8]
- //|.if DUALNUM
- //| mov RD, dword STR:RD->len
- //|1:
- //| mov dword [BASE+RA*8+4], LJ_TISNUM
- //| mov dword [BASE+RA*8], RD
- //|.else
- //| xorps xmm0, xmm0
- //| cvtsi2sd xmm0, dword STR:RD->len
- //|1:
- //| movsd qword [BASE+RA*8], xmm0
- //|.endif
- //| ins_next
- //|2:
- //| checktab RD, ->vmeta_len
- //| mov TAB:FCARG1, [BASE+RD*8]
- dasm_put(Dst, 9923, LJ_TSTR, Dt5(->len), LJ_TISNUM, LJ_TTAB);
- #line 3680 "vm_x86.dasc"
- #if LJ_52
- //| mov TAB:RB, TAB:FCARG1->metatable
- //| cmp TAB:RB, 0
- //| jnz >9
- //|3:
- dasm_put(Dst, 9985, Dt6(->metatable));
- #line 3685 "vm_x86.dasc"
- #endif
- //|->BC_LEN_Z:
- //| mov RB, BASE // Save BASE.
- //| call extern lj_tab_len@4 // (GCtab *t)
- //| // Length of table returned in eax (RD).
- //|.if DUALNUM
- //| // Nothing to do.
- //|.else
- //| cvtsi2sd xmm0, RD
- //|.endif
- //| mov BASE, RB // Restore BASE.
- //| movzx RA, PC_RA
- //| jmp <1
- dasm_put(Dst, 9999);
- #line 3698 "vm_x86.dasc"
- #if LJ_52
- //|9: // Check for __len.
- //| test byte TAB:RB->nomm, 1<<MM_len
- //| jnz <3
- //| jmp ->vmeta_len // 'no __len' flag NOT set: check.
- dasm_put(Dst, 10020, Dt6(->nomm), 1<<MM_len);
- #line 3703 "vm_x86.dasc"
- #endif
- break;
- /* -- Binary ops -------------------------------------------------------- */
- //|.macro ins_arithpre, sseins, ssereg
- //| ins_ABC
- //||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- //||switch (vk) {
- //||case 0:
- //| checknum RB, ->vmeta_arith_vn
- //| .if DUALNUM
- //| cmp dword [KBASE+RC*8+4], LJ_TISNUM; jae ->vmeta_arith_vn
- //| .endif
- //| movsd xmm0, qword [BASE+RB*8]
- //| sseins ssereg, qword [KBASE+RC*8]
- //|| break;
- //||case 1:
- //| checknum RB, ->vmeta_arith_nv
- //| .if DUALNUM
- //| cmp dword [KBASE+RC*8+4], LJ_TISNUM; jae ->vmeta_arith_nv
- //| .endif
- //| movsd xmm0, qword [KBASE+RC*8]
- //| sseins ssereg, qword [BASE+RB*8]
- //|| break;
- //||default:
- //| checknum RB, ->vmeta_arith_vv
- //| checknum RC, ->vmeta_arith_vv
- //| movsd xmm0, qword [BASE+RB*8]
- //| sseins ssereg, qword [BASE+RC*8]
- //|| break;
- //||}
- //|.endmacro
- //|
- //|.macro ins_arithdn, intins
- //| ins_ABC
- //||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- //||switch (vk) {
- //||case 0:
- //| checkint RB, ->vmeta_arith_vn
- //| cmp dword [KBASE+RC*8+4], LJ_TISNUM; jne ->vmeta_arith_vn
- //| mov RB, [BASE+RB*8]
- //| intins RB, [KBASE+RC*8]; jo ->vmeta_arith_vno
- //|| break;
- //||case 1:
- //| checkint RB, ->vmeta_arith_nv
- //| cmp dword [KBASE+RC*8+4], LJ_TISNUM; jne ->vmeta_arith_nv
- //| mov RC, [KBASE+RC*8]
- //| intins RC, [BASE+RB*8]; jo ->vmeta_arith_nvo
- //|| break;
- //||default:
- //| checkint RB, ->vmeta_arith_vv
- //| checkint RC, ->vmeta_arith_vv
- //| mov RB, [BASE+RB*8]
- //| intins RB, [BASE+RC*8]; jo ->vmeta_arith_vvo
- //|| break;
- //||}
- //| mov dword [BASE+RA*8+4], LJ_TISNUM
- //||if (vk == 1) {
- //| mov dword [BASE+RA*8], RC
- //||} else {
- //| mov dword [BASE+RA*8], RB
- //||}
- //| ins_next
- //|.endmacro
- //|
- //|.macro ins_arithpost
- //| movsd qword [BASE+RA*8], xmm0
- //|.endmacro
- //|
- //|.macro ins_arith, sseins
- //| ins_arithpre sseins, xmm0
- //| ins_arithpost
- //| ins_next
- //|.endmacro
- //|
- //|.macro ins_arith, intins, sseins
- //|.if DUALNUM
- //| ins_arithdn intins
- //|.else
- //| ins_arith, sseins
- //|.endif
- //|.endmacro
- //| // RA = dst, RB = src1 or num const, RC = src2 or num const
- case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
- //| ins_arith add, addsd
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10044, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10079, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10114, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- dasm_put(Dst, 10147, LJ_TISNUM);
- if (vk == 1) {
- dasm_put(Dst, 10153);
- } else {
- dasm_put(Dst, 9654);
- }
- dasm_put(Dst, 9224);
- #line 3790 "vm_x86.dasc"
- break;
- case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
- //| ins_arith sub, subsd
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10157, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10192, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10227, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- dasm_put(Dst, 10147, LJ_TISNUM);
- if (vk == 1) {
- dasm_put(Dst, 10153);
- } else {
- dasm_put(Dst, 9654);
- }
- dasm_put(Dst, 9224);
- #line 3793 "vm_x86.dasc"
- break;
- case BC_MULVN: case BC_MULNV: case BC_MULVV:
- //| ins_arith imul, mulsd
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10260, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10296, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10332, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- dasm_put(Dst, 10147, LJ_TISNUM);
- if (vk == 1) {
- dasm_put(Dst, 10153);
- } else {
- dasm_put(Dst, 9654);
- }
- dasm_put(Dst, 9224);
- #line 3796 "vm_x86.dasc"
- break;
- case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
- //| ins_arith divsd
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10366, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10403, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10440, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- dasm_put(Dst, 10475);
- #line 3799 "vm_x86.dasc"
- break;
- case BC_MODVN:
- //| ins_arithpre movsd, xmm1
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10502, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10539, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10576, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- #line 3802 "vm_x86.dasc"
- //|->BC_MODVN_Z:
- //| call ->vm_mod
- //| ins_arithpost
- //| ins_next
- dasm_put(Dst, 10611);
- #line 3806 "vm_x86.dasc"
- break;
- case BC_MODNV: case BC_MODVV:
- //| ins_arithpre movsd, xmm1
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10502, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10539, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10576, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- #line 3809 "vm_x86.dasc"
- //| jmp ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway.
- dasm_put(Dst, 10643);
- #line 3810 "vm_x86.dasc"
- break;
- case BC_POW:
- //| ins_arithpre movsd, xmm1
- dasm_put(Dst, 10036);
- vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
- switch (vk) {
- case 0:
- dasm_put(Dst, 10502, LJ_TISNUM, LJ_TISNUM);
- break;
- case 1:
- dasm_put(Dst, 10539, LJ_TISNUM, LJ_TISNUM);
- break;
- default:
- dasm_put(Dst, 10576, LJ_TISNUM, LJ_TISNUM);
- break;
- }
- #line 3813 "vm_x86.dasc"
- //| mov RB, BASE
- //|.if not X64
- //| movsd FPARG1, xmm0
- //| movsd FPARG3, xmm1
- //|.endif
- //| call extern pow
- //| movzx RA, PC_RA
- //| mov BASE, RB
- //|.if X64
- //| ins_arithpost
- //|.else
- //| fstp qword [BASE+RA*8]
- //|.endif
- //| ins_next
- dasm_put(Dst, 10648);
- #line 3827 "vm_x86.dasc"
- break;
- case BC_CAT:
- //| ins_ABC // RA = dst, RB = src_start, RC = src_end
- //|.if X64
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE
- //| lea CARG2d, [BASE+RC*8]
- //| mov CARG3d, RC
- //| sub CARG3d, RB
- //|->BC_CAT_Z:
- //| mov L:RB, L:CARG1d
- //|.else
- //| lea RA, [BASE+RC*8]
- //| sub RC, RB
- //| mov ARG2, RA
- //| mov ARG3, RC
- //|->BC_CAT_Z:
- //| mov L:RB, SAVE_L
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_meta_cat // (lua_State *L, TValue *top, int left)
- //| // NULL (finished) or TValue * (metamethod) returned in eax (RC).
- //| mov BASE, L:RB->base
- //| test RC, RC
- //| jnz ->vmeta_binop
- //| movzx RB, PC_RB // Copy result to Stk[RA] from Stk[RB].
- //| movzx RA, PC_RA
- //|.if X64
- //| mov RCa, [BASE+RB*8]
- //| mov [BASE+RA*8], RCa
- //|.else
- //| mov RC, [BASE+RB*8+4]
- //| mov RB, [BASE+RB*8]
- //| mov [BASE+RA*8+4], RC
- //| mov [BASE+RA*8], RB
- //|.endif
- //| ins_next
- dasm_put(Dst, 10689, Dt1(->base), Dt1(->base));
- #line 3867 "vm_x86.dasc"
- break;
- /* -- Constant ops ------------------------------------------------------ */
- case BC_KSTR:
- //| ins_AND // RA = dst, RD = str const (~)
- //| mov RD, [KBASE+RD*4]
- //| mov dword [BASE+RA*8+4], LJ_TSTR
- //| mov [BASE+RA*8], RD
- //| ins_next
- dasm_put(Dst, 10773, LJ_TSTR);
- #line 3877 "vm_x86.dasc"
- break;
- case BC_KCDATA:
- //|.if FFI
- //| ins_AND // RA = dst, RD = cdata const (~)
- //| mov RD, [KBASE+RD*4]
- //| mov dword [BASE+RA*8+4], LJ_TCDATA
- //| mov [BASE+RA*8], RD
- //| ins_next
- //|.endif
- dasm_put(Dst, 10773, LJ_TCDATA);
- #line 3886 "vm_x86.dasc"
- break;
- case BC_KSHORT:
- //| ins_AD // RA = dst, RD = signed int16 literal
- //|.if DUALNUM
- //| movsx RD, RDW
- //| mov dword [BASE+RA*8+4], LJ_TISNUM
- //| mov dword [BASE+RA*8], RD
- //|.else
- //| movsx RD, RDW // Sign-extend literal.
- //| cvtsi2sd xmm0, RD
- //| movsd qword [BASE+RA*8], xmm0
- //|.endif
- //| ins_next
- dasm_put(Dst, 10810, LJ_TISNUM);
- #line 3899 "vm_x86.dasc"
- break;
- case BC_KNUM:
- //| ins_AD // RA = dst, RD = num const
- //| movsd xmm0, qword [KBASE+RD*8]
- //| movsd qword [BASE+RA*8], xmm0
- //| ins_next
- dasm_put(Dst, 10842);
- #line 3905 "vm_x86.dasc"
- break;
- case BC_KPRI:
- //| ins_AND // RA = dst, RD = primitive type (~)
- //| mov [BASE+RA*8+4], RD
- //| ins_next
- dasm_put(Dst, 10876);
- #line 3910 "vm_x86.dasc"
- break;
- case BC_KNIL:
- //| ins_AD // RA = dst_start, RD = dst_end
- //| lea RA, [BASE+RA*8+12]
- //| lea RD, [BASE+RD*8+4]
- //| mov RB, LJ_TNIL
- //| mov [RA-8], RB // Sets minimum 2 slots.
- //|1:
- //| mov [RA], RB
- //| add RA, 8
- //| cmp RA, RD
- //| jbe <1
- //| ins_next
- dasm_put(Dst, 10905, LJ_TNIL);
- #line 3923 "vm_x86.dasc"
- break;
- /* -- Upvalue and function ops ------------------------------------------ */
- case BC_UGET:
- //| ins_AD // RA = dst, RD = upvalue #
- //| mov LFUNC:RB, [BASE-8]
- //| mov UPVAL:RB, [LFUNC:RB+RD*4+offsetof(GCfuncL, uvptr)]
- //| mov RB, UPVAL:RB->v
- //|.if X64
- //| mov RDa, [RB]
- //| mov [BASE+RA*8], RDa
- //|.else
- //| mov RD, [RB+4]
- //| mov RB, [RB]
- //| mov [BASE+RA*8+4], RD
- //| mov [BASE+RA*8], RB
- //|.endif
- //| ins_next
- dasm_put(Dst, 10953, offsetof(GCfuncL, uvptr), DtA(->v));
- #line 3942 "vm_x86.dasc"
- break;
- case BC_USETV:
- #define TV2MARKOFS \
- ((int32_t)offsetof(GCupval, marked)-(int32_t)offsetof(GCupval, tv))
- //| ins_AD // RA = upvalue #, RD = src
- //| mov LFUNC:RB, [BASE-8]
- //| mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)]
- //| cmp byte UPVAL:RB->closed, 0
- //| mov RB, UPVAL:RB->v
- //| mov RA, [BASE+RD*8]
- //| mov RD, [BASE+RD*8+4]
- //| mov [RB], RA
- //| mov [RB+4], RD
- //| jz >1
- //| // Check barrier for closed upvalue.
- //| test byte [RB+TV2MARKOFS], LJ_GC_BLACK // isblack(uv)
- //| jnz >2
- //|1:
- //| ins_next
- //|
- //|2: // Upvalue is black. Check if new value is collectable and white.
- //| sub RD, LJ_TISGCV
- //| cmp RD, LJ_TNUMX - LJ_TISGCV // tvisgcv(v)
- //| jbe <1
- //| test byte GCOBJ:RA->gch.marked, LJ_GC_WHITES // iswhite(v)
- //| jz <1
- //| // Crossed a write barrier. Move the barrier forward.
- //|.if X64 and not X64WIN
- //| mov FCARG2, RB
- //| mov RB, BASE // Save BASE.
- //|.else
- //| xchg FCARG2, RB // Save BASE (FCARG2 == BASE).
- //|.endif
- //| lea GL:FCARG1, [DISPATCH+GG_DISP2G]
- //| call extern lj_gc_barrieruv@8 // (global_State *g, TValue *tv)
- dasm_put(Dst, 10994, offsetof(GCfuncL, uvptr), DtA(->closed), DtA(->v), TV2MARKOFS, LJ_GC_BLACK, LJ_TISGCV, LJ_TNUMX - LJ_TISGCV, Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G);
- #line 3977 "vm_x86.dasc"
- //| mov BASE, RB // Restore BASE.
- //| jmp <1
- dasm_put(Dst, 11090);
- #line 3979 "vm_x86.dasc"
- break;
- #undef TV2MARKOFS
- case BC_USETS:
- //| ins_AND // RA = upvalue #, RD = str const (~)
- //| mov LFUNC:RB, [BASE-8]
- //| mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)]
- //| mov GCOBJ:RA, [KBASE+RD*4]
- //| mov RD, UPVAL:RB->v
- //| mov [RD], GCOBJ:RA
- //| mov dword [RD+4], LJ_TSTR
- //| test byte UPVAL:RB->marked, LJ_GC_BLACK // isblack(uv)
- //| jnz >2
- //|1:
- //| ins_next
- //|
- //|2: // Check if string is white and ensure upvalue is closed.
- //| test byte GCOBJ:RA->gch.marked, LJ_GC_WHITES // iswhite(str)
- //| jz <1
- //| cmp byte UPVAL:RB->closed, 0
- //| jz <1
- //| // Crossed a write barrier. Move the barrier forward.
- //| mov RB, BASE // Save BASE (FCARG2 == BASE).
- //| mov FCARG2, RD
- //| lea GL:FCARG1, [DISPATCH+GG_DISP2G]
- //| call extern lj_gc_barrieruv@8 // (global_State *g, TValue *tv)
- //| mov BASE, RB // Restore BASE.
- //| jmp <1
- dasm_put(Dst, 11102, offsetof(GCfuncL, uvptr), DtA(->v), LJ_TSTR, DtA(->marked), LJ_GC_BLACK, Dt4(->gch.marked), LJ_GC_WHITES, DtA(->closed), GG_DISP2G);
- #line 4006 "vm_x86.dasc"
- break;
- case BC_USETN:
- //| ins_AD // RA = upvalue #, RD = num const
- //| mov LFUNC:RB, [BASE-8]
- //| movsd xmm0, qword [KBASE+RD*8]
- //| mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)]
- //| mov RA, UPVAL:RB->v
- //| movsd qword [RA], xmm0
- //| ins_next
- dasm_put(Dst, 11198, offsetof(GCfuncL, uvptr), DtA(->v));
- #line 4015 "vm_x86.dasc"
- break;
- case BC_USETP:
- //| ins_AND // RA = upvalue #, RD = primitive type (~)
- //| mov LFUNC:RB, [BASE-8]
- //| mov UPVAL:RB, [LFUNC:RB+RA*4+offsetof(GCfuncL, uvptr)]
- //| mov RA, UPVAL:RB->v
- //| mov [RA+4], RD
- //| ins_next
- dasm_put(Dst, 11243, offsetof(GCfuncL, uvptr), DtA(->v));
- #line 4023 "vm_x86.dasc"
- break;
- case BC_UCLO:
- //| ins_AD // RA = level, RD = target
- //| branchPC RD // Do this first to free RD.
- //| mov L:RB, SAVE_L
- //| cmp dword L:RB->openupval, 0
- //| je >1
- //| mov L:RB->base, BASE
- //| lea FCARG2, [BASE+RA*8] // Caveat: FCARG2 == BASE
- //| mov L:FCARG1, L:RB // Caveat: FCARG1 == RA
- //| call extern lj_func_closeuv@8 // (lua_State *L, TValue *level)
- //| mov BASE, L:RB->base
- //|1:
- //| ins_next
- dasm_put(Dst, 11283, -BCBIAS_J*4, Dt1(->openupval), Dt1(->base), Dt1(->base));
- #line 4037 "vm_x86.dasc"
- break;
- case BC_FNEW:
- //| ins_AND // RA = dst, RD = proto const (~) (holding function prototype)
- //|.if X64
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Caveat: CARG2d/CARG3d may be BASE.
- //| mov CARG3d, [BASE-8]
- //| mov CARG2d, [KBASE+RD*4] // Fetch GCproto *.
- //| mov CARG1d, L:RB
- //|.else
- //| mov LFUNC:RA, [BASE-8]
- //| mov PROTO:RD, [KBASE+RD*4] // Fetch GCproto *.
- //| mov L:RB, SAVE_L
- //| mov ARG3, LFUNC:RA
- //| mov ARG2, PROTO:RD
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| // (lua_State *L, GCproto *pt, GCfuncL *parent)
- //| call extern lj_func_newL_gc
- //| // GCfuncL * returned in eax (RC).
- //| mov BASE, L:RB->base
- //| movzx RA, PC_RA
- //| mov [BASE+RA*8], LFUNC:RC
- //| mov dword [BASE+RA*8+4], LJ_TFUNC
- //| ins_next
- dasm_put(Dst, 11339, Dt1(->base), Dt1(->base), LJ_TFUNC);
- #line 4065 "vm_x86.dasc"
- break;
- /* -- Table ops --------------------------------------------------------- */
- case BC_TNEW:
- //| ins_AD // RA = dst, RD = hbits|asize
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov RA, [DISPATCH+DISPATCH_GL(gc.total)]
- //| cmp RA, [DISPATCH+DISPATCH_GL(gc.threshold)]
- //| mov SAVE_PC, PC
- //| jae >5
- //|1:
- //|.if X64
- //| mov CARG3d, RD
- //| and RD, 0x7ff
- //| shr CARG3d, 11
- //|.else
- //| mov RA, RD
- //| and RD, 0x7ff
- //| shr RA, 11
- //| mov ARG3, RA
- //|.endif
- //| cmp RD, 0x7ff
- //| je >3
- //|2:
- //|.if X64
- //| mov L:CARG1d, L:RB
- //| mov CARG2d, RD
- //|.else
- //| mov ARG1, L:RB
- //| mov ARG2, RD
- //|.endif
- //| call extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits)
- //| // Table * returned in eax (RC).
- //| mov BASE, L:RB->base
- //| movzx RA, PC_RA
- //| mov [BASE+RA*8], TAB:RC
- //| mov dword [BASE+RA*8+4], LJ_TTAB
- //| ins_next
- //|3: // Turn 0x7ff into 0x801.
- //| mov RD, 0x801
- //| jmp <2
- //|5:
- //| mov L:FCARG1, L:RB
- //| call extern lj_gc_step_fixtop@4 // (lua_State *L)
- //| movzx RD, PC_RD
- //| jmp <1
- dasm_put(Dst, 11406, Dt1(->base), DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), LJ_TTAB);
- #line 4113 "vm_x86.dasc"
- break;
- case BC_TDUP:
- //| ins_AND // RA = dst, RD = table const (~) (holding template table)
- //| mov L:RB, SAVE_L
- //| mov RA, [DISPATCH+DISPATCH_GL(gc.total)]
- //| mov SAVE_PC, PC
- //| cmp RA, [DISPATCH+DISPATCH_GL(gc.threshold)]
- //| mov L:RB->base, BASE
- //| jae >3
- //|2:
- //| mov TAB:FCARG2, [KBASE+RD*4] // Caveat: FCARG2 == BASE
- //| mov L:FCARG1, L:RB // Caveat: FCARG1 == RA
- //| call extern lj_tab_dup@8 // (lua_State *L, Table *kt)
- //| // Table * returned in eax (RC).
- //| mov BASE, L:RB->base
- //| movzx RA, PC_RA
- //| mov [BASE+RA*8], TAB:RC
- //| mov dword [BASE+RA*8+4], LJ_TTAB
- //| ins_next
- //|3:
- //| mov L:FCARG1, L:RB
- //| call extern lj_gc_step_fixtop@4 // (lua_State *L)
- //| movzx RD, PC_RD // Need to reload RD.
- //| not RDa
- //| jmp <2
- dasm_put(Dst, 11530, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base), Dt1(->base), LJ_TTAB);
- #line 4138 "vm_x86.dasc"
- break;
- case BC_GGET:
- //| ins_AND // RA = dst, RD = str const (~)
- //| mov LFUNC:RB, [BASE-8]
- //| mov TAB:RB, LFUNC:RB->env
- //| mov STR:RC, [KBASE+RD*4]
- //| jmp ->BC_TGETS_Z
- dasm_put(Dst, 11629, Dt7(->env));
- #line 4146 "vm_x86.dasc"
- break;
- case BC_GSET:
- //| ins_AND // RA = src, RD = str const (~)
- //| mov LFUNC:RB, [BASE-8]
- //| mov TAB:RB, LFUNC:RB->env
- //| mov STR:RC, [KBASE+RD*4]
- //| jmp ->BC_TSETS_Z
- dasm_put(Dst, 11649, Dt7(->env));
- #line 4153 "vm_x86.dasc"
- break;
- case BC_TGETV:
- //| ins_ABC // RA = dst, RB = table, RC = key
- //| checktab RB, ->vmeta_tgetv
- //| mov TAB:RB, [BASE+RB*8]
- //|
- //| // Integer key?
- //|.if DUALNUM
- //| checkint RC, >5
- //| mov RC, dword [BASE+RC*8]
- //|.else
- //| // Convert number to int and back and compare.
- //| checknum RC, >5
- //| movsd xmm0, qword [BASE+RC*8]
- //| cvttsd2si RC, xmm0
- //| cvtsi2sd xmm1, RC
- //| ucomisd xmm0, xmm1
- //| jne ->vmeta_tgetv // Generic numeric key? Use fallback.
- //|.endif
- //| cmp RC, TAB:RB->asize // Takes care of unordered, too.
- //| jae ->vmeta_tgetv // Not in array part? Use fallback.
- //| shl RC, 3
- //| add RC, TAB:RB->array
- //| cmp dword [RC+4], LJ_TNIL // Avoid overwriting RB in fastpath.
- //| je >2
- //| // Get array slot.
- //|.if X64
- //| mov RBa, [RC]
- //| mov [BASE+RA*8], RBa
- //|.else
- //| mov RB, [RC]
- //| mov RC, [RC+4]
- //| mov [BASE+RA*8], RB
- //| mov [BASE+RA*8+4], RC
- //|.endif
- //|1:
- //| ins_next
- //|
- //|2: // Check for __index if table value is nil.
- //| cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath.
- //| jz >3
- //| mov TAB:RA, TAB:RB->metatable
- //| test byte TAB:RA->nomm, 1<<MM_index
- //| jz ->vmeta_tgetv // 'no __index' flag NOT set: check.
- dasm_put(Dst, 11669, LJ_TTAB, LJ_TISNUM, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
- #line 4198 "vm_x86.dasc"
- //| movzx RA, PC_RA // Restore RA.
- //|3:
- //| mov dword [BASE+RA*8+4], LJ_TNIL
- //| jmp <1
- //|
- //|5: // String key?
- //| checkstr RC, ->vmeta_tgetv
- //| mov STR:RC, [BASE+RC*8]
- //| jmp ->BC_TGETS_Z
- dasm_put(Dst, 11774, LJ_TNIL, LJ_TSTR);
- #line 4207 "vm_x86.dasc"
- break;
- case BC_TGETS:
- //| ins_ABC // RA = dst, RB = table, RC = str const (~)
- //| not RCa
- //| mov STR:RC, [KBASE+RC*4]
- //| checktab RB, ->vmeta_tgets
- //| mov TAB:RB, [BASE+RB*8]
- //|->BC_TGETS_Z: // RB = GCtab *, RC = GCstr *, refetches PC_RA.
- //| mov RA, TAB:RB->hmask
- //| and RA, STR:RC->hash
- //| imul RA, #NODE
- //| add NODE:RA, TAB:RB->node
- //|1:
- //| cmp dword NODE:RA->key.it, LJ_TSTR
- //| jne >4
- //| cmp dword NODE:RA->key.gcr, STR:RC
- //| jne >4
- //| // Ok, key found. Assumes: offsetof(Node, val) == 0
- //| cmp dword [RA+4], LJ_TNIL // Avoid overwriting RB in fastpath.
- //| je >5 // Key found, but nil value?
- //| movzx RC, PC_RA
- //| // Get node value.
- //|.if X64
- //| mov RBa, [RA]
- //| mov [BASE+RC*8], RBa
- //|.else
- //| mov RB, [RA]
- //| mov RA, [RA+4]
- //| mov [BASE+RC*8], RB
- //| mov [BASE+RC*8+4], RA
- //|.endif
- //|2:
- //| ins_next
- dasm_put(Dst, 11814, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL);
- #line 4240 "vm_x86.dasc"
- //|
- //|3:
- //| movzx RC, PC_RA
- //| mov dword [BASE+RC*8+4], LJ_TNIL
- //| jmp <2
- //|
- //|4: // Follow hash chain.
- //| mov NODE:RA, NODE:RA->next
- //| test NODE:RA, NODE:RA
- //| jnz <1
- //| // End of hash chain: key not found, nil result.
- //|
- //|5: // Check for __index if table value is nil.
- //| mov TAB:RA, TAB:RB->metatable
- //| test TAB:RA, TAB:RA
- //| jz <3 // No metatable: done.
- //| test byte TAB:RA->nomm, 1<<MM_index
- //| jnz <3 // 'no __index' flag set: done.
- //| jmp ->vmeta_tgets // Caveat: preserve STR:RC.
- dasm_put(Dst, 11899, LJ_TNIL, DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
- #line 4259 "vm_x86.dasc"
- break;
- case BC_TGETB:
- //| ins_ABC // RA = dst, RB = table, RC = byte literal
- //| checktab RB, ->vmeta_tgetb
- //| mov TAB:RB, [BASE+RB*8]
- //| cmp RC, TAB:RB->asize
- //| jae ->vmeta_tgetb
- //| shl RC, 3
- //| add RC, TAB:RB->array
- //| cmp dword [RC+4], LJ_TNIL // Avoid overwriting RB in fastpath.
- //| je >2
- //| // Get array slot.
- //|.if X64
- //| mov RBa, [RC]
- //| mov [BASE+RA*8], RBa
- //|.else
- //| mov RB, [RC]
- //| mov RC, [RC+4]
- //| mov [BASE+RA*8], RB
- //| mov [BASE+RA*8+4], RC
- //|.endif
- //|1:
- //| ins_next
- //|
- //|2: // Check for __index if table value is nil.
- //| cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath.
- //| jz >3
- //| mov TAB:RA, TAB:RB->metatable
- //| test byte TAB:RA->nomm, 1<<MM_index
- //| jz ->vmeta_tgetb // 'no __index' flag NOT set: check.
- //| movzx RA, PC_RA // Restore RA.
- dasm_put(Dst, 11971, LJ_TTAB, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
- #line 4290 "vm_x86.dasc"
- //|3:
- //| mov dword [BASE+RA*8+4], LJ_TNIL
- //| jmp <1
- dasm_put(Dst, 12067, LJ_TNIL);
- #line 4293 "vm_x86.dasc"
- break;
- case BC_TGETR:
- //| ins_ABC // RA = dst, RB = table, RC = key
- //| mov TAB:RB, [BASE+RB*8]
- //|.if DUALNUM
- //| mov RC, dword [BASE+RC*8]
- //|.else
- //| cvttsd2si RC, qword [BASE+RC*8]
- //|.endif
- //| cmp RC, TAB:RB->asize
- //| jae ->vmeta_tgetr // Not in array part? Use fallback.
- //| shl RC, 3
- //| add RC, TAB:RB->array
- //| // Get array slot.
- //|->BC_TGETR_Z:
- //|.if X64
- //| mov RBa, [RC]
- //| mov [BASE+RA*8], RBa
- //|.else
- //| mov RB, [RC]
- //| mov RC, [RC+4]
- //| mov [BASE+RA*8], RB
- //| mov [BASE+RA*8+4], RC
- //|.endif
- //|->BC_TGETR2_Z:
- //| ins_next
- dasm_put(Dst, 12084, Dt6(->asize), Dt6(->array));
- #line 4319 "vm_x86.dasc"
- break;
- case BC_TSETV:
- //| ins_ABC // RA = src, RB = table, RC = key
- //| checktab RB, ->vmeta_tsetv
- //| mov TAB:RB, [BASE+RB*8]
- //|
- //| // Integer key?
- //|.if DUALNUM
- //| checkint RC, >5
- //| mov RC, dword [BASE+RC*8]
- //|.else
- //| // Convert number to int and back and compare.
- //| checknum RC, >5
- //| movsd xmm0, qword [BASE+RC*8]
- //| cvttsd2si RC, xmm0
- //| cvtsi2sd xmm1, RC
- //| ucomisd xmm0, xmm1
- //| jne ->vmeta_tsetv // Generic numeric key? Use fallback.
- //|.endif
- //| cmp RC, TAB:RB->asize // Takes care of unordered, too.
- //| jae ->vmeta_tsetv
- //| shl RC, 3
- //| add RC, TAB:RB->array
- //| cmp dword [RC+4], LJ_TNIL
- //| je >3 // Previous value is nil?
- //|1:
- //| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
- //| jnz >7
- //|2: // Set array slot.
- //|.if X64
- //| mov RBa, [BASE+RA*8]
- //| mov [RC], RBa
- //|.else
- //| mov RB, [BASE+RA*8+4]
- //| mov RA, [BASE+RA*8]
- //| mov [RC+4], RB
- //| mov [RC], RA
- //|.endif
- //| ins_next
- //|
- //|3: // Check for __newindex if previous value is nil.
- //| cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath.
- dasm_put(Dst, 12143, LJ_TTAB, LJ_TISNUM, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK);
- #line 4362 "vm_x86.dasc"
- //| jz <1
- //| mov TAB:RA, TAB:RB->metatable
- //| test byte TAB:RA->nomm, 1<<MM_newindex
- //| jz ->vmeta_tsetv // 'no __newindex' flag NOT set: check.
- //| movzx RA, PC_RA // Restore RA.
- //| jmp <1
- //|
- //|5: // String key?
- //| checkstr RC, ->vmeta_tsetv
- //| mov STR:RC, [BASE+RC*8]
- //| jmp ->BC_TSETS_Z
- //|
- //|7: // Possible table write barrier for the value. Skip valiswhite check.
- //| barrierback TAB:RB, RA
- dasm_put(Dst, 12243, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex, LJ_TSTR, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain));
- #line 4376 "vm_x86.dasc"
- //| movzx RA, PC_RA // Restore RA.
- //| jmp <2
- dasm_put(Dst, 12302, DISPATCH_GL(gc.grayagain), Dt6(->gclist));
- #line 4378 "vm_x86.dasc"
- break;
- case BC_TSETS:
- //| ins_ABC // RA = src, RB = table, RC = str const (~)
- //| not RCa
- //| mov STR:RC, [KBASE+RC*4]
- //| checktab RB, ->vmeta_tsets
- //| mov TAB:RB, [BASE+RB*8]
- //|->BC_TSETS_Z: // RB = GCtab *, RC = GCstr *, refetches PC_RA.
- //| mov RA, TAB:RB->hmask
- //| and RA, STR:RC->hash
- //| imul RA, #NODE
- //| mov byte TAB:RB->nomm, 0 // Clear metamethod cache.
- //| add NODE:RA, TAB:RB->node
- //|1:
- //| cmp dword NODE:RA->key.it, LJ_TSTR
- //| jne >5
- //| cmp dword NODE:RA->key.gcr, STR:RC
- //| jne >5
- //| // Ok, key found. Assumes: offsetof(Node, val) == 0
- //| cmp dword [RA+4], LJ_TNIL
- //| je >4 // Previous value is nil?
- //|2:
- //| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
- dasm_put(Dst, 12319, LJ_TTAB, Dt6(->hmask), Dt5(->hash), sizeof(Node), Dt6(->nomm), Dt6(->node), DtB(->key.it), LJ_TSTR, DtB(->key.gcr), LJ_TNIL);
- #line 4401 "vm_x86.dasc"
- //| jnz >7
- //|3: // Set node value.
- //| movzx RC, PC_RA
- //|.if X64
- //| mov RBa, [BASE+RC*8]
- //| mov [RA], RBa
- //|.else
- //| mov RB, [BASE+RC*8+4]
- //| mov RC, [BASE+RC*8]
- //| mov [RA+4], RB
- //| mov [RA], RC
- //|.endif
- //| ins_next
- //|
- //|4: // Check for __newindex if previous value is nil.
- //| cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath.
- //| jz <2
- //| mov TMP1, RA // Save RA.
- //| mov TAB:RA, TAB:RB->metatable
- //| test byte TAB:RA->nomm, 1<<MM_newindex
- //| jz ->vmeta_tsets // 'no __newindex' flag NOT set: check.
- //| mov RA, TMP1 // Restore RA.
- //| jmp <2
- //|
- //|5: // Follow hash chain.
- //| mov NODE:RA, NODE:RA->next
- //| test NODE:RA, NODE:RA
- //| jnz <1
- //| // End of hash chain: key not found, add a new one.
- //|
- //| // But check for __newindex first.
- //| mov TAB:RA, TAB:RB->metatable
- dasm_put(Dst, 12396, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex, DtB(->next));
- #line 4433 "vm_x86.dasc"
- //| test TAB:RA, TAB:RA
- //| jz >6 // No metatable: continue.
- //| test byte TAB:RA->nomm, 1<<MM_newindex
- //| jz ->vmeta_tsets // 'no __newindex' flag NOT set: check.
- //|6:
- //| mov TMP1, STR:RC
- //| mov TMP2, LJ_TSTR
- //| mov TMP3, TAB:RB // Save TAB:RB for us.
- //|.if X64
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE
- //| lea CARG3, TMP1
- //| mov CARG2d, TAB:RB
- //| mov L:RB, L:CARG1d
- //|.else
- //| lea RC, TMP1 // Store temp. TValue in TMP1/TMP2.
- //| mov ARG2, TAB:RB
- //| mov L:RB, SAVE_L
- //| mov ARG3, RC
- //| mov ARG1, L:RB
- //| mov L:RB->base, BASE
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k)
- //| // Handles write barrier for the new key. TValue * returned in eax (RC).
- //| mov BASE, L:RB->base
- //| mov TAB:RB, TMP3 // Need TAB:RB for barrier.
- //| mov RA, eax
- //| jmp <2 // Must check write barrier for value.
- //|
- //|7: // Possible table write barrier for the value. Skip valiswhite check.
- //| barrierback TAB:RB, RC // Destroys STR:RC.
- //| jmp <3
- dasm_put(Dst, 12483, Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex, LJ_TSTR, Dt1(->base), Dt1(->base), Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist));
- #line 4466 "vm_x86.dasc"
- break;
- case BC_TSETB:
- //| ins_ABC // RA = src, RB = table, RC = byte literal
- //| checktab RB, ->vmeta_tsetb
- //| mov TAB:RB, [BASE+RB*8]
- //| cmp RC, TAB:RB->asize
- //| jae ->vmeta_tsetb
- //| shl RC, 3
- //| add RC, TAB:RB->array
- //| cmp dword [RC+4], LJ_TNIL
- //| je >3 // Previous value is nil?
- //|1:
- //| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
- //| jnz >7
- //|2: // Set array slot.
- //|.if X64
- //| mov RAa, [BASE+RA*8]
- //| mov [RC], RAa
- //|.else
- //| mov RB, [BASE+RA*8+4]
- //| mov RA, [BASE+RA*8]
- //| mov [RC+4], RB
- //| mov [RC], RA
- //|.endif
- //| ins_next
- //|
- //|3: // Check for __newindex if previous value is nil.
- //| cmp dword TAB:RB->metatable, 0 // Shouldn't overwrite RA for fastpath.
- //| jz <1
- //| mov TAB:RA, TAB:RB->metatable
- dasm_put(Dst, 12575, LJ_TTAB, Dt6(->asize), Dt6(->array), LJ_TNIL, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable));
- #line 4496 "vm_x86.dasc"
- //| test byte TAB:RA->nomm, 1<<MM_newindex
- //| jz ->vmeta_tsetb // 'no __newindex' flag NOT set: check.
- //| movzx RA, PC_RA // Restore RA.
- //| jmp <1
- //|
- //|7: // Possible table write barrier for the value. Skip valiswhite check.
- //| barrierback TAB:RB, RA
- //| movzx RA, PC_RA // Restore RA.
- //| jmp <2
- dasm_put(Dst, 12670, Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist));
- #line 4505 "vm_x86.dasc"
- break;
- case BC_TSETR:
- //| ins_ABC // RA = src, RB = table, RC = key
- //| mov TAB:RB, [BASE+RB*8]
- //|.if DUALNUM
- //| mov RC, dword [BASE+RC*8]
- //|.else
- //| cvttsd2si RC, qword [BASE+RC*8]
- //|.endif
- //| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
- //| jnz >7
- //|2:
- //| cmp RC, TAB:RB->asize
- //| jae ->vmeta_tsetr
- //| shl RC, 3
- //| add RC, TAB:RB->array
- //| // Set array slot.
- //|->BC_TSETR_Z:
- //|.if X64
- //| mov RBa, [BASE+RA*8]
- //| mov [RC], RBa
- //|.else
- //| mov RB, [BASE+RA*8+4]
- //| mov RA, [BASE+RA*8]
- //| mov [RC+4], RB
- //| mov [RC], RA
- //|.endif
- //| ins_next
- //|
- //|7: // Possible table write barrier for the value. Skip valiswhite check.
- //| barrierback TAB:RB, RA
- //| movzx RA, PC_RA // Restore RA.
- //| jmp <2
- dasm_put(Dst, 12718, Dt6(->marked), LJ_GC_BLACK, Dt6(->asize), Dt6(->array), Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist));
- #line 4538 "vm_x86.dasc"
- break;
- case BC_TSETM:
- //| ins_AD // RA = base (table at base-1), RD = num const (start index)
- //| mov TMP1, KBASE // Need one more free register.
- //| mov KBASE, dword [KBASE+RD*8] // Integer constant is in lo-word.
- //|1:
- //| lea RA, [BASE+RA*8]
- //| mov TAB:RB, [RA-8] // Guaranteed to be a table.
- //| test byte TAB:RB->marked, LJ_GC_BLACK // isblack(table)
- //| jnz >7
- //|2:
- //| mov RD, MULTRES
- //| sub RD, 1
- //| jz >4 // Nothing to copy?
- //| add RD, KBASE // Compute needed size.
- //| cmp RD, TAB:RB->asize
- //| ja >5 // Doesn't fit into array part?
- //| sub RD, KBASE
- //| shl KBASE, 3
- //| add KBASE, TAB:RB->array
- //|3: // Copy result slots to table.
- //|.if X64
- //| mov RBa, [RA]
- //| add RA, 8
- //| mov [KBASE], RBa
- //|.else
- //| mov RB, [RA]
- //| mov [KBASE], RB
- //| mov RB, [RA+4]
- //| add RA, 8
- //| mov [KBASE+4], RB
- //|.endif
- //| add KBASE, 8
- //| sub RD, 1
- //| jnz <3
- //|4:
- //| mov KBASE, TMP1
- //| ins_next
- //|
- //|5: // Need to resize array part.
- //|.if X64
- //| mov L:CARG1d, SAVE_L
- //| mov L:CARG1d->base, BASE // Caveat: CARG2d/CARG3d may be BASE.
- //| mov CARG2d, TAB:RB
- //| mov CARG3d, RD
- //| mov L:RB, L:CARG1d
- //|.else
- //| mov ARG2, TAB:RB
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE
- //| mov ARG3, RD
- //| mov ARG1, L:RB
- //|.endif
- //| mov SAVE_PC, PC
- //| call extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize)
- //| mov BASE, L:RB->base
- //| movzx RA, PC_RA // Restore RA.
- //| jmp <1 // Retry.
- //|
- //|7: // Possible table write barrier for any value. Skip valiswhite check.
- //| barrierback TAB:RB, RD
- dasm_put(Dst, 12812, Dt6(->marked), LJ_GC_BLACK, Dt6(->asize), Dt6(->array), Dt1(->base), Dt1(->base));
- #line 4600 "vm_x86.dasc"
- //| jmp <2
- dasm_put(Dst, 12962, Dt6(->marked), (uint8_t)~LJ_GC_BLACK, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->gclist));
- #line 4601 "vm_x86.dasc"
- break;
- /* -- Calls and vararg handling ----------------------------------------- */
- case BC_CALL: case BC_CALLM:
- //| ins_A_C // RA = base, (RB = nresults+1,) RC = nargs+1 | extra_nargs
- dasm_put(Dst, 10040);
- #line 4607 "vm_x86.dasc"
- if (op == BC_CALLM) {
- //| add NARGS:RD, MULTRES
- dasm_put(Dst, 12982);
- #line 4609 "vm_x86.dasc"
- }
- //| cmp dword [BASE+RA*8+4], LJ_TFUNC
- //| mov LFUNC:RB, [BASE+RA*8]
- //| jne ->vmeta_call_ra
- //| lea BASE, [BASE+RA*8+8]
- //| ins_call
- dasm_put(Dst, 12987, LJ_TFUNC, Dt7(->pc));
- #line 4615 "vm_x86.dasc"
- break;
- case BC_CALLMT:
- //| ins_AD // RA = base, RD = extra_nargs
- //| add NARGS:RD, MULTRES
- //| // Fall through. Assumes BC_CALLT follows and ins_AD is a no-op.
- dasm_put(Dst, 12982);
- #line 4621 "vm_x86.dasc"
- break;
- case BC_CALLT:
- //| ins_AD // RA = base, RD = nargs+1
- //| lea RA, [BASE+RA*8+8]
- //| mov KBASE, BASE // Use KBASE for move + vmeta_call hint.
- //| mov LFUNC:RB, [RA-8]
- //| cmp dword [RA-4], LJ_TFUNC
- //| jne ->vmeta_call
- //|->BC_CALLT_Z:
- //| mov PC, [BASE-4]
- //| test PC, FRAME_TYPE
- //| jnz >7
- //|1:
- //| mov [BASE-8], LFUNC:RB // Copy function down, reloaded below.
- //| mov MULTRES, NARGS:RD
- //| sub NARGS:RD, 1
- //| jz >3
- //|2: // Move args down.
- //|.if X64
- //| mov RBa, [RA]
- //| add RA, 8
- //| mov [KBASE], RBa
- //|.else
- //| mov RB, [RA]
- //| mov [KBASE], RB
- //| mov RB, [RA+4]
- //| add RA, 8
- //| mov [KBASE+4], RB
- //|.endif
- //| add KBASE, 8
- //| sub NARGS:RD, 1
- //| jnz <2
- //|
- //| mov LFUNC:RB, [BASE-8]
- //|3:
- //| mov NARGS:RD, MULTRES
- //| cmp byte LFUNC:RB->ffid, 1 // (> FF_C) Calling a fast function?
- //| ja >5
- //|4:
- //| ins_callt
- //|
- //|5: // Tailcall to a fast function.
- //| test PC, FRAME_TYPE // Lua frame below?
- dasm_put(Dst, 13030, LJ_TFUNC, FRAME_TYPE, Dt7(->ffid), Dt7(->pc));
- #line 4664 "vm_x86.dasc"
- //| jnz <4
- //| movzx RA, PC_RA
- //| not RAa
- //| mov LFUNC:KBASE, [BASE+RA*8-8] // Need to prepare KBASE.
- //| mov KBASE, LFUNC:KBASE->pc
- //| mov KBASE, [KBASE+PC2PROTO(k)]
- //| jmp <4
- //|
- //|7: // Tailcall from a vararg function.
- //| sub PC, FRAME_VARG
- //| test PC, FRAME_TYPEP
- //| jnz >8 // Vararg frame below?
- //| sub BASE, PC // Need to relocate BASE/KBASE down.
- //| mov KBASE, BASE
- //| mov PC, [BASE-4]
- //| jmp <1
- //|8:
- //| add PC, FRAME_VARG
- //| jmp <1
- dasm_put(Dst, 13148, FRAME_TYPE, Dt7(->pc), PC2PROTO(k), FRAME_VARG, FRAME_TYPEP, FRAME_VARG);
- #line 4683 "vm_x86.dasc"
- break;
- case BC_ITERC:
- //| ins_A // RA = base, (RB = nresults+1,) RC = nargs+1 (2+1)
- //| lea RA, [BASE+RA*8+8] // fb = base+1
- //|.if X64
- //| mov RBa, [RA-24] // Copy state. fb[0] = fb[-3].
- //| mov RCa, [RA-16] // Copy control var. fb[1] = fb[-2].
- //| mov [RA], RBa
- //| mov [RA+8], RCa
- //|.else
- //| mov RB, [RA-24] // Copy state. fb[0] = fb[-3].
- //| mov RC, [RA-20]
- //| mov [RA], RB
- //| mov [RA+4], RC
- //| mov RB, [RA-16] // Copy control var. fb[1] = fb[-2].
- //| mov RC, [RA-12]
- //| mov [RA+8], RB
- //| mov [RA+12], RC
- //|.endif
- //| mov LFUNC:RB, [RA-32] // Copy callable. fb[-1] = fb[-4]
- //| mov RC, [RA-28]
- //| mov [RA-8], LFUNC:RB
- //| mov [RA-4], RC
- //| cmp RC, LJ_TFUNC // Handle like a regular 2-arg call.
- //| mov NARGS:RD, 2+1
- //| jne ->vmeta_call
- //| mov BASE, RA
- //| ins_call
- dasm_put(Dst, 13220, LJ_TFUNC, 2+1, Dt7(->pc));
- #line 4712 "vm_x86.dasc"
- break;
- case BC_ITERN:
- //| ins_A // RA = base, (RB = nresults+1, RC = nargs+1 (2+1))
- //|.if JIT
- //| // NYI: add hotloop, record BC_ITERN.
- //|.endif
- //| mov TMP1, KBASE // Need two more free registers.
- //| mov TMP2, DISPATCH
- //| mov TAB:RB, [BASE+RA*8-16]
- //| mov RC, [BASE+RA*8-8] // Get index from control var.
- //| mov DISPATCH, TAB:RB->asize
- //| add PC, 4
- //| mov KBASE, TAB:RB->array
- //|1: // Traverse array part.
- //| cmp RC, DISPATCH; jae >5 // Index points after array part?
- //| cmp dword [KBASE+RC*8+4], LJ_TNIL; je >4
- //|.if DUALNUM
- //| mov dword [BASE+RA*8+4], LJ_TISNUM
- //| mov dword [BASE+RA*8], RC
- //|.else
- //| cvtsi2sd xmm0, RC
- //|.endif
- //| // Copy array slot to returned value.
- //|.if X64
- //| mov RBa, [KBASE+RC*8]
- //| mov [BASE+RA*8+8], RBa
- //|.else
- //| mov RB, [KBASE+RC*8+4]
- //| mov [BASE+RA*8+12], RB
- //| mov RB, [KBASE+RC*8]
- //| mov [BASE+RA*8+8], RB
- //|.endif
- //| add RC, 1
- //| // Return array index as a numeric key.
- //|.if DUALNUM
- //| // See above.
- //|.else
- //| movsd qword [BASE+RA*8], xmm0
- //|.endif
- //| mov [BASE+RA*8-8], RC // Update control var.
- //|2:
- //| movzx RD, PC_RD // Get target from ITERL.
- //| branchPC RD
- //|3:
- //| mov DISPATCH, TMP2
- //| mov KBASE, TMP1
- //| ins_next
- //|
- //|4: // Skip holes in array part.
- //| add RC, 1
- //| jmp <1
- //|
- //|5: // Traverse hash part.
- //| sub RC, DISPATCH
- //|6:
- //| cmp RC, TAB:RB->hmask; ja <3 // End of iteration? Branch to ITERL+1.
- //| imul KBASE, RC, #NODE
- dasm_put(Dst, 13292, Dt6(->asize), Dt6(->array), LJ_TNIL, LJ_TISNUM, -BCBIAS_J*4, Dt6(->hmask));
- #line 4770 "vm_x86.dasc"
- //| add NODE:KBASE, TAB:RB->node
- //| cmp dword NODE:KBASE->val.it, LJ_TNIL; je >7
- //| lea DISPATCH, [RC+DISPATCH+1]
- //| // Copy key and value from hash slot.
- //|.if X64
- //| mov RBa, NODE:KBASE->key
- //| mov RCa, NODE:KBASE->val
- //| mov [BASE+RA*8], RBa
- //| mov [BASE+RA*8+8], RCa
- //|.else
- //| mov RB, NODE:KBASE->key.gcr
- //| mov RC, NODE:KBASE->key.it
- //| mov [BASE+RA*8], RB
- //| mov [BASE+RA*8+4], RC
- //| mov RB, NODE:KBASE->val.gcr
- //| mov RC, NODE:KBASE->val.it
- //| mov [BASE+RA*8+8], RB
- //| mov [BASE+RA*8+12], RC
- //|.endif
- //| mov [BASE+RA*8-8], DISPATCH
- //| jmp <2
- //|
- //|7: // Skip holes in hash part.
- //| add RC, 1
- //| jmp <6
- dasm_put(Dst, 13436, sizeof(Node), Dt6(->node), DtB(->val.it), LJ_TNIL, DtB(->key), DtB(->val));
- #line 4795 "vm_x86.dasc"
- break;
- case BC_ISNEXT:
- //| ins_AD // RA = base, RD = target (points to ITERN)
- //| cmp dword [BASE+RA*8-20], LJ_TFUNC; jne >5
- //| mov CFUNC:RB, [BASE+RA*8-24]
- //| cmp dword [BASE+RA*8-12], LJ_TTAB; jne >5
- //| cmp dword [BASE+RA*8-4], LJ_TNIL; jne >5
- //| cmp byte CFUNC:RB->ffid, FF_next_N; jne >5
- //| branchPC RD
- //| mov dword [BASE+RA*8-8], 0 // Initialize control var.
- //| mov dword [BASE+RA*8-4], 0xfffe7fff
- //|1:
- //| ins_next
- //|5: // Despecialize bytecode if any of the checks fail.
- //| mov PC_OP, BC_JMP
- //| branchPC RD
- //| mov byte [PC], BC_ITERC
- //| jmp <1
- dasm_put(Dst, 13496, LJ_TFUNC, LJ_TTAB, LJ_TNIL, Dt8(->ffid), FF_next_N, -BCBIAS_J*4, BC_JMP, -BCBIAS_J*4, BC_ITERC);
- #line 4814 "vm_x86.dasc"
- break;
- case BC_VARG:
- //| ins_ABC // RA = base, RB = nresults+1, RC = numparams
- //| mov TMP1, KBASE // Need one more free register.
- //| lea KBASE, [BASE+RC*8+(8+FRAME_VARG)]
- //| lea RA, [BASE+RA*8]
- //| sub KBASE, [BASE-4]
- //| // Note: KBASE may now be even _above_ BASE if nargs was < numparams.
- //| test RB, RB
- //| jz >5 // Copy all varargs?
- //| lea RB, [RA+RB*8-8]
- //| cmp KBASE, BASE // No vararg slots?
- //| jnb >2
- //|1: // Copy vararg slots to destination slots.
- //|.if X64
- //| mov RCa, [KBASE-8]
- //| add KBASE, 8
- //| mov [RA], RCa
- //|.else
- //| mov RC, [KBASE-8]
- //| mov [RA], RC
- //| mov RC, [KBASE-4]
- //| add KBASE, 8
- //| mov [RA+4], RC
- //|.endif
- //| add RA, 8
- //| cmp RA, RB // All destination slots filled?
- //| jnb >3
- //| cmp KBASE, BASE // No more vararg slots?
- //| jb <1
- //|2: // Fill up remainder with nil.
- //| mov dword [RA+4], LJ_TNIL
- //| add RA, 8
- //| cmp RA, RB
- //| jb <2
- //|3:
- //| mov KBASE, TMP1
- //| ins_next
- //|
- //|5: // Copy all varargs.
- //| mov MULTRES, 1 // MULTRES = 0+1
- //| mov RC, BASE
- //| sub RC, KBASE
- //| jbe <3 // No vararg slots?
- //| mov RB, RC
- //| shr RB, 3
- //| add RB, 1
- //| mov MULTRES, RB // MULTRES = #varargs+1
- //| mov L:RB, SAVE_L
- //| add RC, RA
- //| cmp RC, L:RB->maxstack
- //| ja >7 // Need to grow stack?
- //|6: // Copy all vararg slots.
- //|.if X64
- //| mov RCa, [KBASE-8]
- dasm_put(Dst, 13609, (8+FRAME_VARG), LJ_TNIL, Dt1(->maxstack));
- #line 4870 "vm_x86.dasc"
- //| add KBASE, 8
- //| mov [RA], RCa
- //|.else
- //| mov RC, [KBASE-8]
- //| mov [RA], RC
- //| mov RC, [KBASE-4]
- //| add KBASE, 8
- //| mov [RA+4], RC
- //|.endif
- //| add RA, 8
- //| cmp KBASE, BASE // No more vararg slots?
- //| jb <6
- //| jmp <3
- //|
- //|7: // Grow stack for varargs.
- //| mov L:RB->base, BASE
- //| mov L:RB->top, RA
- //| mov SAVE_PC, PC
- //| sub KBASE, BASE // Need delta, because BASE may change.
- //| mov FCARG2, MULTRES
- //| sub FCARG2, 1
- //| mov FCARG1, L:RB
- //| call extern lj_state_growstack@8 // (lua_State *L, int n)
- //| mov BASE, L:RB->base
- //| mov RA, L:RB->top
- //| add KBASE, BASE
- //| jmp <6
- dasm_put(Dst, 13776, Dt1(->base), Dt1(->top), Dt1(->base), Dt1(->top));
- #line 4897 "vm_x86.dasc"
- break;
- /* -- Returns ----------------------------------------------------------- */
- case BC_RETM:
- //| ins_AD // RA = results, RD = extra_nresults
- //| add RD, MULTRES // MULTRES >=1, so RD >=1.
- //| // Fall through. Assumes BC_RET follows and ins_AD is a no-op.
- dasm_put(Dst, 12982);
- #line 4905 "vm_x86.dasc"
- break;
- case BC_RET: case BC_RET0: case BC_RET1:
- //| ins_AD // RA = results, RD = nresults+1
- if (op != BC_RET0) {
- //| shl RA, 3
- dasm_put(Dst, 13846);
- #line 4911 "vm_x86.dasc"
- }
- //|1:
- //| mov PC, [BASE-4]
- //| mov MULTRES, RD // Save nresults+1.
- //| test PC, FRAME_TYPE // Check frame type marker.
- //| jnz >7 // Not returning to a fixarg Lua func?
- dasm_put(Dst, 13850, FRAME_TYPE);
- #line 4917 "vm_x86.dasc"
- switch (op) {
- case BC_RET:
- //|->BC_RET_Z:
- //| mov KBASE, BASE // Use KBASE for result move.
- //| sub RD, 1
- //| jz >3
- //|2: // Move results down.
- //|.if X64
- //| mov RBa, [KBASE+RA]
- //| mov [KBASE-8], RBa
- //|.else
- //| mov RB, [KBASE+RA]
- //| mov [KBASE-8], RB
- //| mov RB, [KBASE+RA+4]
- //| mov [KBASE-4], RB
- //|.endif
- //| add KBASE, 8
- //| sub RD, 1
- //| jnz <2
- //|3:
- //| mov RD, MULTRES // Note: MULTRES may be >255.
- //| movzx RB, PC_RB // So cannot compare with RDL!
- //|5:
- //| cmp RB, RD // More results expected?
- //| ja >6
- dasm_put(Dst, 13869);
- #line 4942 "vm_x86.dasc"
- break;
- case BC_RET1:
- //|.if X64
- //| mov RBa, [BASE+RA]
- //| mov [BASE-8], RBa
- //|.else
- //| mov RB, [BASE+RA+4]
- //| mov [BASE-4], RB
- //| mov RB, [BASE+RA]
- //| mov [BASE-8], RB
- //|.endif
- dasm_put(Dst, 13923);
- #line 4953 "vm_x86.dasc"
- /* fallthrough */
- case BC_RET0:
- //|5:
- //| cmp PC_RB, RDL // More results expected?
- //| ja >6
- dasm_put(Dst, 13933);
- #line 4958 "vm_x86.dasc"
- default:
- break;
- }
- //| movzx RA, PC_RA
- //| not RAa // Note: ~RA = -(RA+1)
- //| lea BASE, [BASE+RA*8] // base = base - (RA+1)*8
- //| mov LFUNC:KBASE, [BASE-8]
- //| mov KBASE, LFUNC:KBASE->pc
- //| mov KBASE, [KBASE+PC2PROTO(k)]
- //| ins_next
- //|
- //|6: // Fill up results with nil.
- dasm_put(Dst, 13944, Dt7(->pc), PC2PROTO(k));
- #line 4970 "vm_x86.dasc"
- if (op == BC_RET) {
- //| mov dword [KBASE-4], LJ_TNIL // Note: relies on shifted base.
- //| add KBASE, 8
- dasm_put(Dst, 13992, LJ_TNIL);
- #line 4973 "vm_x86.dasc"
- } else {
- //| mov dword [BASE+RD*8-12], LJ_TNIL
- dasm_put(Dst, 14003, LJ_TNIL);
- #line 4975 "vm_x86.dasc"
- }
- //| add RD, 1
- //| jmp <5
- //|
- //|7: // Non-standard return case.
- //| lea RB, [PC-FRAME_VARG]
- //| test RB, FRAME_TYPEP
- //| jnz ->vm_return
- //| // Return from vararg function: relocate BASE down and RA up.
- //| sub BASE, RB
- dasm_put(Dst, 14010, -FRAME_VARG, FRAME_TYPEP);
- #line 4985 "vm_x86.dasc"
- if (op != BC_RET0) {
- //| add RA, RB
- dasm_put(Dst, 14034);
- #line 4987 "vm_x86.dasc"
- }
- //| jmp <1
- dasm_put(Dst, 10015);
- #line 4989 "vm_x86.dasc"
- break;
- /* -- Loops and branches ------------------------------------------------ */
- //|.define FOR_IDX, [RA]; .define FOR_TIDX, dword [RA+4]
- //|.define FOR_STOP, [RA+8]; .define FOR_TSTOP, dword [RA+12]
- //|.define FOR_STEP, [RA+16]; .define FOR_TSTEP, dword [RA+20]
- //|.define FOR_EXT, [RA+24]; .define FOR_TEXT, dword [RA+28]
- case BC_FORL:
- //|.if JIT
- //| hotloop RB
- //|.endif
- //| // Fall through. Assumes BC_IFORL follows and ins_AJ is a no-op.
- dasm_put(Dst, 14038, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP);
- #line 5003 "vm_x86.dasc"
- break;
- case BC_JFORI:
- case BC_JFORL:
- #if !LJ_HASJIT
- break;
- #endif
- case BC_FORI:
- case BC_IFORL:
- vk = (op == BC_IFORL || op == BC_JFORL);
- //| ins_AJ // RA = base, RD = target (after end of loop or start of loop)
- //| lea RA, [BASE+RA*8]
- dasm_put(Dst, 14059);
- #line 5015 "vm_x86.dasc"
- if (LJ_DUALNUM) {
- //| cmp FOR_TIDX, LJ_TISNUM; jne >9
- dasm_put(Dst, 14063, LJ_TISNUM);
- #line 5017 "vm_x86.dasc"
- if (!vk) {
- //| cmp FOR_TSTOP, LJ_TISNUM; jne ->vmeta_for
- //| cmp FOR_TSTEP, LJ_TISNUM; jne ->vmeta_for
- //| mov RB, dword FOR_IDX
- //| cmp dword FOR_STEP, 0; jl >5
- dasm_put(Dst, 14073, LJ_TISNUM, LJ_TISNUM);
- #line 5022 "vm_x86.dasc"
- } else {
- #ifdef LUA_USE_ASSERT
- //| cmp FOR_TSTOP, LJ_TISNUM; jne ->assert_bad_for_arg_type
- //| cmp FOR_TSTEP, LJ_TISNUM; jne ->assert_bad_for_arg_type
- dasm_put(Dst, 14102, LJ_TISNUM, LJ_TISNUM);
- #line 5026 "vm_x86.dasc"
- #endif
- //| mov RB, dword FOR_STEP
- //| test RB, RB; js >5
- //| add RB, dword FOR_IDX; jo >1
- //| mov dword FOR_IDX, RB
- dasm_put(Dst, 14121);
- #line 5031 "vm_x86.dasc"
- }
- //| cmp RB, dword FOR_STOP
- //| mov FOR_TEXT, LJ_TISNUM
- //| mov dword FOR_EXT, RB
- dasm_put(Dst, 14140, LJ_TISNUM);
- #line 5035 "vm_x86.dasc"
- if (op == BC_FORI) {
- //| jle >7
- //|1:
- //|6:
- //| branchPC RD
- dasm_put(Dst, 14151, -BCBIAS_J*4);
- #line 5040 "vm_x86.dasc"
- } else if (op == BC_JFORI) {
- //| branchPC RD
- //| movzx RD, PC_RD
- //| jle =>BC_JLOOP
- //|1:
- //|6:
- dasm_put(Dst, 14165, -BCBIAS_J*4, BC_JLOOP);
- #line 5046 "vm_x86.dasc"
- } else if (op == BC_IFORL) {
- //| jg >7
- //|6:
- //| branchPC RD
- //|1:
- dasm_put(Dst, 14183, -BCBIAS_J*4);
- #line 5051 "vm_x86.dasc"
- } else {
- //| jle =>BC_JLOOP
- //|1:
- //|6:
- dasm_put(Dst, 14175, BC_JLOOP);
- #line 5055 "vm_x86.dasc"
- }
- //|7:
- //| ins_next
- //|
- //|5: // Invert check for negative step.
- dasm_put(Dst, 14197);
- #line 5060 "vm_x86.dasc"
- if (vk) {
- //| add RB, dword FOR_IDX; jo <1
- //| mov dword FOR_IDX, RB
- dasm_put(Dst, 14222);
- #line 5063 "vm_x86.dasc"
- }
- //| cmp RB, dword FOR_STOP
- //| mov FOR_TEXT, LJ_TISNUM
- //| mov dword FOR_EXT, RB
- dasm_put(Dst, 14140, LJ_TISNUM);
- #line 5067 "vm_x86.dasc"
- if (op == BC_FORI) {
- //| jge <7
- dasm_put(Dst, 14231);
- #line 5069 "vm_x86.dasc"
- } else if (op == BC_JFORI) {
- //| branchPC RD
- //| movzx RD, PC_RD
- //| jge =>BC_JLOOP
- dasm_put(Dst, 14236, -BCBIAS_J*4, BC_JLOOP);
- #line 5073 "vm_x86.dasc"
- } else if (op == BC_IFORL) {
- //| jl <7
- dasm_put(Dst, 14250);
- #line 5075 "vm_x86.dasc"
- } else {
- //| jge =>BC_JLOOP
- dasm_put(Dst, 14246, BC_JLOOP);
- #line 5077 "vm_x86.dasc"
- }
- //| jmp <6
- //|9: // Fallback to FP variant.
- dasm_put(Dst, 14255);
- #line 5080 "vm_x86.dasc"
- } else if (!vk) {
- //| cmp FOR_TIDX, LJ_TISNUM
- dasm_put(Dst, 14262, LJ_TISNUM);
- #line 5082 "vm_x86.dasc"
- }
- if (!vk) {
- //| jae ->vmeta_for
- //| cmp FOR_TSTOP, LJ_TISNUM; jae ->vmeta_for
- dasm_put(Dst, 14268, LJ_TISNUM);
- #line 5086 "vm_x86.dasc"
- } else {
- #ifdef LUA_USE_ASSERT
- //| cmp FOR_TSTOP, LJ_TISNUM; jae ->assert_bad_for_arg_type
- //| cmp FOR_TSTEP, LJ_TISNUM; jae ->assert_bad_for_arg_type
- dasm_put(Dst, 14282, LJ_TISNUM, LJ_TISNUM);
- #line 5090 "vm_x86.dasc"
- #endif
- }
- //| mov RB, FOR_TSTEP // Load type/hiword of for step.
- dasm_put(Dst, 14301);
- #line 5093 "vm_x86.dasc"
- if (!vk) {
- //| cmp RB, LJ_TISNUM; jae ->vmeta_for
- dasm_put(Dst, 14305, LJ_TISNUM);
- #line 5095 "vm_x86.dasc"
- }
- //| movsd xmm0, qword FOR_IDX
- //| movsd xmm1, qword FOR_STOP
- dasm_put(Dst, 14314);
- #line 5098 "vm_x86.dasc"
- if (vk) {
- //| addsd xmm0, qword FOR_STEP
- //| movsd qword FOR_IDX, xmm0
- //| test RB, RB; js >3
- dasm_put(Dst, 14326);
- #line 5102 "vm_x86.dasc"
- } else {
- //| jl >3
- dasm_put(Dst, 14345);
- #line 5104 "vm_x86.dasc"
- }
- //| ucomisd xmm1, xmm0
- //|1:
- //| movsd qword FOR_EXT, xmm0
- dasm_put(Dst, 14350);
- #line 5108 "vm_x86.dasc"
- if (op == BC_FORI) {
- //|.if DUALNUM
- //| jnb <7
- //|.else
- //| jnb >2
- //| branchPC RD
- //|.endif
- dasm_put(Dst, 14363);
- #line 5115 "vm_x86.dasc"
- } else if (op == BC_JFORI) {
- //| branchPC RD
- //| movzx RD, PC_RD
- //| jnb =>BC_JLOOP
- dasm_put(Dst, 14368, -BCBIAS_J*4, BC_JLOOP);
- #line 5119 "vm_x86.dasc"
- } else if (op == BC_IFORL) {
- //|.if DUALNUM
- //| jb <7
- //|.else
- //| jb >2
- //| branchPC RD
- //|.endif
- dasm_put(Dst, 14382);
- #line 5126 "vm_x86.dasc"
- } else {
- //| jnb =>BC_JLOOP
- dasm_put(Dst, 14378, BC_JLOOP);
- #line 5128 "vm_x86.dasc"
- }
- //|.if DUALNUM
- //| jmp <6
- //|.else
- //|2:
- //| ins_next
- //|.endif
- //|
- //|3: // Invert comparison if step is negative.
- //| ucomisd xmm0, xmm1
- //| jmp <1
- dasm_put(Dst, 14387);
- #line 5139 "vm_x86.dasc"
- break;
- case BC_ITERL:
- //|.if JIT
- //| hotloop RB
- //|.endif
- //| // Fall through. Assumes BC_IITERL follows and ins_AJ is a no-op.
- dasm_put(Dst, 14038, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP);
- #line 5146 "vm_x86.dasc"
- break;
- case BC_JITERL:
- #if !LJ_HASJIT
- break;
- #endif
- case BC_IITERL:
- //| ins_AJ // RA = base, RD = target
- //| lea RA, [BASE+RA*8]
- //| mov RB, [RA+4]
- //| cmp RB, LJ_TNIL; je >1 // Stop if iterator returned nil.
- dasm_put(Dst, 14402, LJ_TNIL);
- #line 5157 "vm_x86.dasc"
- if (op == BC_JITERL) {
- //| mov [RA-4], RB
- //| mov RB, [RA]
- //| mov [RA-8], RB
- //| jmp =>BC_JLOOP
- dasm_put(Dst, 14417, BC_JLOOP);
- #line 5162 "vm_x86.dasc"
- } else {
- //| branchPC RD // Otherwise save control var + branch.
- //| mov RD, [RA]
- //| mov [RA-4], RB
- //| mov [RA-8], RD
- dasm_put(Dst, 14431, -BCBIAS_J*4);
- #line 5167 "vm_x86.dasc"
- }
- //|1:
- //| ins_next
- dasm_put(Dst, 9668);
- #line 5170 "vm_x86.dasc"
- break;
- case BC_LOOP:
- //| ins_A // RA = base, RD = target (loop extent)
- //| // Note: RA/RD is only used by trace recorder to determine scope/extent
- //| // This opcode does NOT jump, it's only purpose is to detect a hot loop.
- //|.if JIT
- //| hotloop RB
- //|.endif
- //| // Fall through. Assumes BC_ILOOP follows and ins_A is a no-op.
- dasm_put(Dst, 14038, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_LOOP);
- #line 5180 "vm_x86.dasc"
- break;
- case BC_ILOOP:
- //| ins_A // RA = base, RD = target (loop extent)
- //| ins_next
- dasm_put(Dst, 9224);
- #line 5185 "vm_x86.dasc"
- break;
- case BC_JLOOP:
- //|.if JIT
- //| ins_AD // RA = base (ignored), RD = traceno
- #ifdef LUA_USE_TRACE_LOGS
- //|.if X64
- //| mov L:RB, SAVE_L
- //| mov L:RB->base, BASE // Save BASE
- //| mov TMP1, RD // Save RD
- //| mov CARG3d, PC // CARG3d == BASE
- //| mov FCARG2, RD
- //| mov FCARG1, RB
- //| call extern lj_log_trace_entry@8
- //| mov RD, TMP1
- //| mov BASE, L:RB->base
- //|.endif
- dasm_put(Dst, 14447, Dt1(->base), Dt1(->base));
- #line 5202 "vm_x86.dasc"
- #endif
- //| mov RA, [DISPATCH+DISPATCH_J(trace)]
- //| mov TRACE:RD, [RA+RD*4]
- //| mov RDa, TRACE:RD->mcode
- //| mov L:RB, SAVE_L
- //| mov [DISPATCH+DISPATCH_GL(jit_base)], BASE
- //| mov [DISPATCH+DISPATCH_GL(tmpbuf.L)], L:RB
- //| // Save additional callee-save registers only used in compiled code.
- //|.if X64WIN
- //| mov TMPQ, r12
- //| mov TMPa, r13
- //| mov CSAVE_4, r14
- //| mov CSAVE_3, r15
- //| mov RAa, rsp
- //| sub rsp, 9*16+4*8
- //| movdqa [RAa], xmm6
- //| movdqa [RAa-1*16], xmm7
- //| movdqa [RAa-2*16], xmm8
- //| movdqa [RAa-3*16], xmm9
- //| movdqa [RAa-4*16], xmm10
- //| movdqa [RAa-5*16], xmm11
- //| movdqa [RAa-6*16], xmm12
- //| movdqa [RAa-7*16], xmm13
- //| movdqa [RAa-8*16], xmm14
- //| movdqa [RAa-9*16], xmm15
- //|.elif X64
- //| mov TMPQ, r12
- //| mov TMPa, r13
- //| sub rsp, 16
- //|.endif
- //| jmp RDa
- //|.endif
- dasm_put(Dst, 14475, DISPATCH_J(trace), DtD(->mcode), DISPATCH_GL(jit_base), DISPATCH_GL(tmpbuf.L));
- #line 5234 "vm_x86.dasc"
- break;
- case BC_JMP:
- //| ins_AJ // RA = unused, RD = target
- //| branchPC RD
- //| ins_next
- dasm_put(Dst, 14516, -BCBIAS_J*4);
- #line 5240 "vm_x86.dasc"
- break;
- /* -- Function headers -------------------------------------------------- */
- /*
- ** Reminder: A function may be called with func/args above L->maxstack,
- ** i.e. occupying EXTRA_STACK slots. And vmeta_call may add one extra slot,
- ** too. This means all FUNC* ops (including fast functions) must check
- ** for stack overflow _before_ adding more slots!
- */
- case BC_FUNCF:
- //|.if JIT
- //| hotcall RB
- //|.endif
- dasm_put(Dst, 14542, HOTCOUNT_PCMASK, GG_DISP2HOT, HOTCOUNT_CALL);
- #line 5255 "vm_x86.dasc"
- case BC_FUNCV: /* NYI: compiled vararg functions. */
- //| // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow and ins_AD is a no-op.
- break;
- case BC_JFUNCF:
- #if !LJ_HASJIT
- break;
- #endif
- case BC_IFUNCF:
- //| ins_AD // BASE = new base, RA = framesize, RD = nargs+1
- //| mov KBASE, [PC-4+PC2PROTO(k)]
- //| mov L:RB, SAVE_L
- //| lea RA, [BASE+RA*8] // Top of frame.
- //| cmp RA, L:RB->maxstack
- //| ja ->vm_growstack_f
- //| movzx RA, byte [PC-4+PC2PROTO(numparams)]
- //| cmp NARGS:RD, RA // Check for missing parameters.
- //| jbe >3
- //|2:
- dasm_put(Dst, 14563, -4+PC2PROTO(k), Dt1(->maxstack), -4+PC2PROTO(numparams));
- #line 5274 "vm_x86.dasc"
- if (op == BC_JFUNCF) {
- //| movzx RD, PC_RD
- //| jmp =>BC_JLOOP
- dasm_put(Dst, 14594, BC_JLOOP);
- #line 5277 "vm_x86.dasc"
- } else {
- //| ins_next
- dasm_put(Dst, 9224);
- #line 5279 "vm_x86.dasc"
- }
- //|
- //|3: // Clear missing parameters.
- //| mov dword [BASE+NARGS:RD*8-4], LJ_TNIL
- //| add NARGS:RD, 1
- //| cmp NARGS:RD, RA
- //| jbe <3
- //| jmp <2
- dasm_put(Dst, 14603, LJ_TNIL);
- #line 5287 "vm_x86.dasc"
- break;
- case BC_JFUNCV:
- #if !LJ_HASJIT
- break;
- #endif
- //| int3 // NYI: compiled vararg functions
- dasm_put(Dst, 8467);
- #line 5294 "vm_x86.dasc"
- break; /* NYI: compiled vararg functions. */
- case BC_IFUNCV:
- //| ins_AD // BASE = new base, RA = framesize, RD = nargs+1
- //| lea RB, [NARGS:RD*8+FRAME_VARG]
- //| lea RD, [BASE+NARGS:RD*8]
- //| mov LFUNC:KBASE, [BASE-8]
- //| mov [RD-4], RB // Store delta + FRAME_VARG.
- //| mov [RD-8], LFUNC:KBASE // Store copy of LFUNC.
- //| mov L:RB, SAVE_L
- //| lea RA, [RD+RA*8]
- //| cmp RA, L:RB->maxstack
- //| ja ->vm_growstack_v // Need to grow stack.
- //| mov RA, BASE
- //| mov BASE, RD
- //| movzx RB, byte [PC-4+PC2PROTO(numparams)]
- //| test RB, RB
- //| jz >2
- //|1: // Copy fixarg slots up to new frame.
- //| add RA, 8
- //| cmp RA, BASE
- //| jnb >3 // Less args than parameters?
- //| mov KBASE, [RA-8]
- //| mov [RD], KBASE
- //| mov KBASE, [RA-4]
- //| mov [RD+4], KBASE
- //| add RD, 8
- //| mov dword [RA-4], LJ_TNIL // Clear old fixarg slot (help the GC).
- //| sub RB, 1
- //| jnz <1
- //|2:
- dasm_put(Dst, 14625, FRAME_VARG, Dt1(->maxstack), -4+PC2PROTO(numparams), LJ_TNIL);
- #line 5325 "vm_x86.dasc"
- if (op == BC_JFUNCV) {
- //| movzx RD, PC_RD
- //| jmp =>BC_JLOOP
- dasm_put(Dst, 14594, BC_JLOOP);
- #line 5328 "vm_x86.dasc"
- } else {
- //| mov KBASE, [PC-4+PC2PROTO(k)]
- //| ins_next
- dasm_put(Dst, 14722, -4+PC2PROTO(k));
- #line 5331 "vm_x86.dasc"
- }
- //|
- //|3: // Clear missing parameters.
- //| mov dword [RD+4], LJ_TNIL
- //| add RD, 8
- //| sub RB, 1
- //| jnz <3
- //| jmp <2
- dasm_put(Dst, 14747, LJ_TNIL);
- #line 5339 "vm_x86.dasc"
- break;
- case BC_FUNCC:
- case BC_FUNCCW:
- //| ins_AD // BASE = new base, RA = ins RA|RD (unused), RD = nargs+1
- //| mov CFUNC:RB, [BASE-8]
- //| mov KBASEa, CFUNC:RB->f
- //| mov L:RB, SAVE_L
- //| lea RD, [BASE+NARGS:RD*8-8]
- //| mov L:RB->base, BASE
- //| lea RA, [RD+8*LUA_MINSTACK]
- //| cmp RA, L:RB->maxstack
- //| mov L:RB->top, RD
- dasm_put(Dst, 14769, Dt8(->f), Dt1(->base), 8*LUA_MINSTACK, Dt1(->maxstack), Dt1(->top));
- #line 5352 "vm_x86.dasc"
- if (op == BC_FUNCC) {
- //|.if X64
- //| mov CARG1d, L:RB // Caveat: CARG1d may be RA.
- //|.else
- //| mov ARG1, L:RB
- //|.endif
- dasm_put(Dst, 14799);
- #line 5358 "vm_x86.dasc"
- } else {
- //|.if X64
- //| mov CARG2, KBASEa
- //| mov CARG1d, L:RB // Caveat: CARG1d may be RA.
- //|.else
- //| mov ARG2, KBASEa
- //| mov ARG1, L:RB
- //|.endif
- dasm_put(Dst, 14803);
- #line 5366 "vm_x86.dasc"
- }
- //| ja ->vm_growstack_c // Need to grow stack.
- //| set_vmstate C
- dasm_put(Dst, 14811, DISPATCH_GL(vmstate), ~LJ_VMST_C);
- #line 5369 "vm_x86.dasc"
- if (op == BC_FUNCC) {
- //| call KBASEa // (lua_State *L)
- dasm_put(Dst, 14821);
- #line 5371 "vm_x86.dasc"
- } else {
- //| // (lua_State *L, lua_CFunction f)
- //| call aword [DISPATCH+DISPATCH_GL(wrapf)]
- dasm_put(Dst, 14826, DISPATCH_GL(wrapf));
- #line 5374 "vm_x86.dasc"
- }
- //| // nresults returned in eax (RD).
- //| mov BASE, L:RB->base
- //| mov [DISPATCH+DISPATCH_GL(cur_L)], L:RB
- //| set_vmstate INTERP
- //| lea RA, [BASE+RD*8]
- //| neg RA
- //| add RA, L:RB->top // RA = (L->top-(L->base+nresults))*8
- //| mov PC, [BASE-4] // Fetch PC of caller.
- //| jmp ->vm_returnc
- dasm_put(Dst, 14832, Dt1(->base), DISPATCH_GL(cur_L), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->top));
- #line 5384 "vm_x86.dasc"
- break;
- /* ---------------------------------------------------------------------- */
- default:
- fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
- exit(2);
- break;
- }
- }
- static int build_backend(BuildCtx *ctx)
- {
- int op;
- dasm_growpc(Dst, BC__MAX);
- build_subroutines(ctx);
- //|.code_op
- dasm_put(Dst, 14862);
- #line 5401 "vm_x86.dasc"
- for (op = 0; op < BC__MAX; op++)
- build_ins(ctx, (BCOp)op, op);
- return BC__MAX;
- }
- /* Emit pseudo frame-info for all assembler functions. */
- static void emit_asm_debug(BuildCtx *ctx)
- {
- int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code);
- #if LJ_64
- #define SZPTR "8"
- #define BSZPTR "3"
- #define REG_SP "0x7"
- #define REG_RA "0x10"
- #else
- #define SZPTR "4"
- #define BSZPTR "2"
- #define REG_SP "0x4"
- #define REG_RA "0x8"
- #endif
- switch (ctx->mode) {
- case BUILD_elfasm:
- fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n");
- fprintf(ctx->fp,
- ".Lframe0:\n"
- "\t.long .LECIE0-.LSCIE0\n"
- ".LSCIE0:\n"
- "\t.long 0xffffffff\n"
- "\t.byte 0x1\n"
- "\t.string \"\"\n"
- "\t.uleb128 0x1\n"
- "\t.sleb128 -" SZPTR "\n"
- "\t.byte " REG_RA "\n"
- "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n"
- "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n"
- "\t.align " SZPTR "\n"
- ".LECIE0:\n\n");
- fprintf(ctx->fp,
- ".LSFDE0:\n"
- "\t.long .LEFDE0-.LASFDE0\n"
- ".LASFDE0:\n"
- "\t.long .Lframe0\n"
- #if LJ_64
- "\t.quad .Lbegin\n"
- "\t.quad %d\n"
- "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */
- "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */
- "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */
- "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */
- "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */
- #else
- "\t.long .Lbegin\n"
- "\t.long %d\n"
- "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */
- "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */
- "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */
- "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */
- "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */
- #endif
- "\t.align " SZPTR "\n"
- ".LEFDE0:\n\n", fcofs, CFRAME_SIZE);
- #if LJ_HASFFI
- fprintf(ctx->fp,
- ".LSFDE1:\n"
- "\t.long .LEFDE1-.LASFDE1\n"
- ".LASFDE1:\n"
- "\t.long .Lframe0\n"
- #if LJ_64
- "\t.quad lj_vm_ffi_call\n"
- "\t.quad %d\n"
- "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */
- "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */
- "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */
- "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */
- #else
- "\t.long lj_vm_ffi_call\n"
- "\t.long %d\n"
- "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */
- "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */
- "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */
- "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */
- #endif
- "\t.align " SZPTR "\n"
- ".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
- #endif
- #if (defined(__sun__) && defined(__svr4__))
- #if LJ_64
- fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@unwind\n");
- #else
- fprintf(ctx->fp, "\t.section .eh_frame,\"aw\",@progbits\n");
- #endif
- #else
- fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
- #endif
- fprintf(ctx->fp,
- ".Lframe1:\n"
- "\t.long .LECIE1-.LSCIE1\n"
- ".LSCIE1:\n"
- "\t.long 0\n"
- "\t.byte 0x1\n"
- "\t.string \"zPR\"\n"
- "\t.uleb128 0x1\n"
- "\t.sleb128 -" SZPTR "\n"
- "\t.byte " REG_RA "\n"
- "\t.uleb128 6\n" /* augmentation length */
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.long lj_err_unwind_dwarf-.\n"
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n"
- "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n"
- "\t.align " SZPTR "\n"
- ".LECIE1:\n\n");
- fprintf(ctx->fp,
- ".LSFDE2:\n"
- "\t.long .LEFDE2-.LASFDE2\n"
- ".LASFDE2:\n"
- "\t.long .LASFDE2-.Lframe1\n"
- "\t.long .Lbegin-.\n"
- "\t.long %d\n"
- "\t.uleb128 0\n" /* augmentation length */
- "\t.byte 0xe\n\t.uleb128 %d\n" /* def_cfa_offset */
- #if LJ_64
- "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */
- "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */
- "\t.byte 0x8f\n\t.uleb128 0x4\n" /* offset r15 */
- "\t.byte 0x8e\n\t.uleb128 0x5\n" /* offset r14 */
- #else
- "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */
- "\t.byte 0x87\n\t.uleb128 0x3\n" /* offset edi */
- "\t.byte 0x86\n\t.uleb128 0x4\n" /* offset esi */
- "\t.byte 0x83\n\t.uleb128 0x5\n" /* offset ebx */
- #endif
- "\t.align " SZPTR "\n"
- ".LEFDE2:\n\n", fcofs, CFRAME_SIZE);
- #if LJ_HASFFI
- fprintf(ctx->fp,
- ".Lframe2:\n"
- "\t.long .LECIE2-.LSCIE2\n"
- ".LSCIE2:\n"
- "\t.long 0\n"
- "\t.byte 0x1\n"
- "\t.string \"zR\"\n"
- "\t.uleb128 0x1\n"
- "\t.sleb128 -" SZPTR "\n"
- "\t.byte " REG_RA "\n"
- "\t.uleb128 1\n" /* augmentation length */
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.byte 0xc\n\t.uleb128 " REG_SP "\n\t.uleb128 " SZPTR "\n"
- "\t.byte 0x80+" REG_RA "\n\t.uleb128 0x1\n"
- "\t.align " SZPTR "\n"
- ".LECIE2:\n\n");
- fprintf(ctx->fp,
- ".LSFDE3:\n"
- "\t.long .LEFDE3-.LASFDE3\n"
- ".LASFDE3:\n"
- "\t.long .LASFDE3-.Lframe2\n"
- "\t.long lj_vm_ffi_call-.\n"
- "\t.long %d\n"
- "\t.uleb128 0\n" /* augmentation length */
- #if LJ_64
- "\t.byte 0xe\n\t.uleb128 16\n" /* def_cfa_offset */
- "\t.byte 0x86\n\t.uleb128 0x2\n" /* offset rbp */
- "\t.byte 0xd\n\t.uleb128 0x6\n" /* def_cfa_register rbp */
- "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset rbx */
- #else
- "\t.byte 0xe\n\t.uleb128 8\n" /* def_cfa_offset */
- "\t.byte 0x85\n\t.uleb128 0x2\n" /* offset ebp */
- "\t.byte 0xd\n\t.uleb128 0x5\n" /* def_cfa_register ebp */
- "\t.byte 0x83\n\t.uleb128 0x3\n" /* offset ebx */
- #endif
- "\t.align " SZPTR "\n"
- ".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
- #endif
- break;
- /* Mental note: never let Apple design an assembler.
- ** Or a linker. Or a plastic case. But I digress.
- */
- case BUILD_machasm: {
- #if LJ_HASFFI
- int fcsize = 0;
- #endif
- int i;
- fprintf(ctx->fp, "\t.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support\n");
- fprintf(ctx->fp,
- "EH_frame1:\n"
- "\t.set L$set$x,LECIEX-LSCIEX\n"
- "\t.long L$set$x\n"
- "LSCIEX:\n"
- "\t.long 0\n"
- "\t.byte 0x1\n"
- "\t.ascii \"zPR\\0\"\n"
- "\t.byte 0x1\n"
- "\t.byte 128-" SZPTR "\n"
- "\t.byte " REG_RA "\n"
- "\t.byte 6\n" /* augmentation length */
- "\t.byte 0x9b\n" /* indirect|pcrel|sdata4 */
- #if LJ_64
- "\t.long _lj_err_unwind_dwarf+4@GOTPCREL\n"
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n"
- #else
- "\t.long L_lj_err_unwind_dwarf$non_lazy_ptr-.\n"
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH-O. */
- #endif
- "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n"
- "\t.align " BSZPTR "\n"
- "LECIEX:\n\n");
- for (i = 0; i < ctx->nsym; i++) {
- const char *name = ctx->sym[i].name;
- int32_t size = ctx->sym[i+1].ofs - ctx->sym[i].ofs;
- if (size == 0) continue;
- #if LJ_HASFFI
- if (!strcmp(name, "_lj_vm_ffi_call")) { fcsize = size; continue; }
- #endif
- fprintf(ctx->fp,
- "%s.eh:\n"
- "LSFDE%d:\n"
- "\t.set L$set$%d,LEFDE%d-LASFDE%d\n"
- "\t.long L$set$%d\n"
- "LASFDE%d:\n"
- "\t.long LASFDE%d-EH_frame1\n"
- "\t.long %s-.\n"
- "\t.long %d\n"
- "\t.byte 0\n" /* augmentation length */
- "\t.byte 0xe\n\t.byte %d\n" /* def_cfa_offset */
- #if LJ_64
- "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */
- "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */
- "\t.byte 0x8f\n\t.byte 0x4\n" /* offset r15 */
- "\t.byte 0x8e\n\t.byte 0x5\n" /* offset r14 */
- #else
- "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/
- "\t.byte 0x87\n\t.byte 0x3\n" /* offset edi */
- "\t.byte 0x86\n\t.byte 0x4\n" /* offset esi */
- "\t.byte 0x83\n\t.byte 0x5\n" /* offset ebx */
- #endif
- "\t.align " BSZPTR "\n"
- "LEFDE%d:\n\n",
- name, i, i, i, i, i, i, i, name, size, CFRAME_SIZE, i);
- }
- #if LJ_HASFFI
- if (fcsize) {
- fprintf(ctx->fp,
- "EH_frame2:\n"
- "\t.set L$set$y,LECIEY-LSCIEY\n"
- "\t.long L$set$y\n"
- "LSCIEY:\n"
- "\t.long 0\n"
- "\t.byte 0x1\n"
- "\t.ascii \"zR\\0\"\n"
- "\t.byte 0x1\n"
- "\t.byte 128-" SZPTR "\n"
- "\t.byte " REG_RA "\n"
- "\t.byte 1\n" /* augmentation length */
- #if LJ_64
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.byte 0xc\n\t.byte " REG_SP "\n\t.byte " SZPTR "\n"
- #else
- "\t.byte 0x1b\n" /* pcrel|sdata4 */
- "\t.byte 0xc\n\t.byte 0x5\n\t.byte 0x4\n" /* esp=5 on 32 bit MACH. */
- #endif
- "\t.byte 0x80+" REG_RA "\n\t.byte 0x1\n"
- "\t.align " BSZPTR "\n"
- "LECIEY:\n\n");
- fprintf(ctx->fp,
- "_lj_vm_ffi_call.eh:\n"
- "LSFDEY:\n"
- "\t.set L$set$yy,LEFDEY-LASFDEY\n"
- "\t.long L$set$yy\n"
- "LASFDEY:\n"
- "\t.long LASFDEY-EH_frame2\n"
- "\t.long _lj_vm_ffi_call-.\n"
- "\t.long %d\n"
- "\t.byte 0\n" /* augmentation length */
- #if LJ_64
- "\t.byte 0xe\n\t.byte 16\n" /* def_cfa_offset */
- "\t.byte 0x86\n\t.byte 0x2\n" /* offset rbp */
- "\t.byte 0xd\n\t.byte 0x6\n" /* def_cfa_register rbp */
- "\t.byte 0x83\n\t.byte 0x3\n" /* offset rbx */
- #else
- "\t.byte 0xe\n\t.byte 8\n" /* def_cfa_offset */
- "\t.byte 0x84\n\t.byte 0x2\n" /* offset ebp (4 for MACH-O)*/
- "\t.byte 0xd\n\t.byte 0x4\n" /* def_cfa_register ebp */
- "\t.byte 0x83\n\t.byte 0x3\n" /* offset ebx */
- #endif
- "\t.align " BSZPTR "\n"
- "LEFDEY:\n\n", fcsize);
- }
- #endif
- #if !LJ_64
- fprintf(ctx->fp,
- "\t.non_lazy_symbol_pointer\n"
- "L_lj_err_unwind_dwarf$non_lazy_ptr:\n"
- ".indirect_symbol _lj_err_unwind_dwarf\n"
- ".long 0\n\n");
- fprintf(ctx->fp, "\t.section __IMPORT,__jump_table,symbol_stubs,pure_instructions+self_modifying_code,5\n");
- {
- const char *const *xn;
- for (xn = ctx->extnames; *xn; xn++)
- if (strncmp(*xn, LABEL_PREFIX, sizeof(LABEL_PREFIX)-1))
- fprintf(ctx->fp, "L_%s$stub:\n\t.indirect_symbol _%s\n\t.ascii \"\\364\\364\\364\\364\\364\"\n", *xn, *xn);
- }
- #endif
- fprintf(ctx->fp, ".subsections_via_symbols\n");
- }
- break;
- default: /* Difficult for other modes. */
- break;
- }
- }