Rev 7693 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7696 | akron1 | 1 | (* |
7597 | akron1 | 2 | BSD 2-Clause License |
6613 | leency | 3 | |
7696 | akron1 | 4 | Copyright (c) 2018-2019, Anton Krotov |
7597 | akron1 | 5 | All rights reserved. |
6613 | leency | 6 | *) |
7 | |||
8 | MODULE X86; |
||
9 | |||
7693 | akron1 | 10 | IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG, |
11 | mConst := CONSTANTS, CHL := CHUNKLISTS, PATHS; |
||
6613 | leency | 12 | |
7597 | akron1 | 13 | |
6613 | leency | 14 | CONST |
15 | |||
7597 | akron1 | 16 | eax = REG.R0; ecx = REG.R1; edx = REG.R2; |
6613 | leency | 17 | |
7597 | akron1 | 18 | al = eax; cl = ecx; dl = edx; ah = 4; |
6613 | leency | 19 | |
7597 | akron1 | 20 | ax = eax; cx = ecx; dx = edx; |
6613 | leency | 21 | |
7597 | akron1 | 22 | esp = 4; |
23 | ebp = 5; |
||
6613 | leency | 24 | |
7597 | akron1 | 25 | sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H; |
6613 | leency | 26 | |
7597 | akron1 | 27 | je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H; |
6613 | leency | 28 | |
29 | |||
7597 | akron1 | 30 | CODECHUNK = 8; |
6613 | leency | 31 | |
32 | |||
33 | TYPE |
||
34 | |||
7693 | akron1 | 35 | COMMAND = IL.COMMAND; |
6613 | leency | 36 | |
37 | |||
7597 | akron1 | 38 | ANYCODE = POINTER TO RECORD (LISTS.ITEM) |
6613 | leency | 39 | |
7597 | akron1 | 40 | offset: INTEGER |
6613 | leency | 41 | |
7597 | akron1 | 42 | END; |
6613 | leency | 43 | |
7693 | akron1 | 44 | CODE = POINTER TO RECORD (ANYCODE) |
6613 | leency | 45 | |
7597 | akron1 | 46 | code: ARRAY CODECHUNK OF BYTE; |
47 | length: INTEGER |
||
6613 | leency | 48 | |
7597 | akron1 | 49 | END; |
6613 | leency | 50 | |
7597 | akron1 | 51 | LABEL = POINTER TO RECORD (ANYCODE) |
6613 | leency | 52 | |
7597 | akron1 | 53 | label: INTEGER |
6613 | leency | 54 | |
7597 | akron1 | 55 | END; |
6613 | leency | 56 | |
7597 | akron1 | 57 | JUMP = POINTER TO RECORD (ANYCODE) |
7209 | akron1 | 58 | |
7597 | akron1 | 59 | label, diff: INTEGER; |
60 | short: BOOLEAN |
||
6613 | leency | 61 | |
7597 | akron1 | 62 | END; |
6613 | leency | 63 | |
7597 | akron1 | 64 | JMP = POINTER TO RECORD (JUMP) |
6613 | leency | 65 | |
7597 | akron1 | 66 | END; |
6613 | leency | 67 | |
7597 | akron1 | 68 | JCC = POINTER TO RECORD (JUMP) |
6613 | leency | 69 | |
7597 | akron1 | 70 | jmp: INTEGER |
6613 | leency | 71 | |
72 | END; |
||
73 | |||
7597 | akron1 | 74 | CALL = POINTER TO RECORD (JUMP) |
6613 | leency | 75 | |
7597 | akron1 | 76 | END; |
6613 | leency | 77 | |
7597 | akron1 | 78 | RELOC = POINTER TO RECORD (ANYCODE) |
6613 | leency | 79 | |
7597 | akron1 | 80 | op, value: INTEGER |
6613 | leency | 81 | |
7597 | akron1 | 82 | END; |
6613 | leency | 83 | |
84 | |||
7597 | akron1 | 85 | VAR |
6613 | leency | 86 | |
7597 | akron1 | 87 | R: REG.REGS; |
6613 | leency | 88 | |
7597 | akron1 | 89 | program: BIN.PROGRAM; |
6613 | leency | 90 | |
7597 | akron1 | 91 | CodeList: LISTS.LIST; |
6613 | leency | 92 | |
7693 | akron1 | 93 | tcount: INTEGER; |
6613 | leency | 94 | |
7693 | akron1 | 95 | |
7597 | akron1 | 96 | PROCEDURE Byte (n: INTEGER): BYTE; |
7693 | akron1 | 97 | RETURN UTILS.Byte(n, 0) |
7597 | akron1 | 98 | END Byte; |
6613 | leency | 99 | |
100 | |||
7597 | akron1 | 101 | PROCEDURE Word (n: INTEGER): INTEGER; |
7693 | akron1 | 102 | RETURN UTILS.Byte(n, 0) + UTILS.Byte(n, 1) * 256 |
7597 | akron1 | 103 | END Word; |
6613 | leency | 104 | |
105 | |||
7597 | akron1 | 106 | PROCEDURE OutByte* (n: BYTE); |
107 | VAR |
||
7693 | akron1 | 108 | c: CODE; |
7597 | akron1 | 109 | last: ANYCODE; |
6613 | leency | 110 | |
7597 | akron1 | 111 | BEGIN |
112 | last := CodeList.last(ANYCODE); |
||
6613 | leency | 113 | |
7693 | akron1 | 114 | IF (last IS CODE) & (last(CODE).length < CODECHUNK) THEN |
115 | c := last(CODE); |
||
7597 | akron1 | 116 | c.code[c.length] := n; |
117 | INC(c.length) |
||
118 | ELSE |
||
119 | NEW(c); |
||
120 | c.code[0] := n; |
||
121 | c.length := 1; |
||
122 | LISTS.push(CodeList, c) |
||
123 | END |
||
6613 | leency | 124 | |
7597 | akron1 | 125 | END OutByte; |
6613 | leency | 126 | |
127 | |||
7597 | akron1 | 128 | PROCEDURE OutInt (n: INTEGER); |
6613 | leency | 129 | BEGIN |
7693 | akron1 | 130 | OutByte(UTILS.Byte(n, 0)); |
131 | OutByte(UTILS.Byte(n, 1)); |
||
132 | OutByte(UTILS.Byte(n, 2)); |
||
133 | OutByte(UTILS.Byte(n, 3)) |
||
7597 | akron1 | 134 | END OutInt; |
6613 | leency | 135 | |
136 | |||
7597 | akron1 | 137 | PROCEDURE OutByte2 (a, b: BYTE); |
6613 | leency | 138 | BEGIN |
7597 | akron1 | 139 | OutByte(a); |
140 | OutByte(b) |
||
141 | END OutByte2; |
||
6613 | leency | 142 | |
143 | |||
7597 | akron1 | 144 | PROCEDURE OutByte3 (a, b, c: BYTE); |
6613 | leency | 145 | BEGIN |
7597 | akron1 | 146 | OutByte(a); |
147 | OutByte(b); |
||
148 | OutByte(c) |
||
149 | END OutByte3; |
||
6613 | leency | 150 | |
151 | |||
7597 | akron1 | 152 | PROCEDURE OutWord (n: INTEGER); |
6613 | leency | 153 | BEGIN |
7597 | akron1 | 154 | ASSERT((0 <= n) & (n <= 65535)); |
155 | OutByte2(n MOD 256, n DIV 256) |
||
156 | END OutWord; |
||
6613 | leency | 157 | |
158 | |||
7597 | akron1 | 159 | PROCEDURE isByte (n: INTEGER): BOOLEAN; |
160 | RETURN (-128 <= n) & (n <= 127) |
||
161 | END isByte; |
||
162 | |||
163 | |||
164 | PROCEDURE short (n: INTEGER): INTEGER; |
||
165 | RETURN 2 * ORD(isByte(n)) |
||
166 | END short; |
||
167 | |||
168 | |||
169 | PROCEDURE long (n: INTEGER): INTEGER; |
||
170 | RETURN 40H * ORD(~isByte(n)) |
||
171 | END long; |
||
172 | |||
173 | |||
174 | PROCEDURE OutIntByte (n: INTEGER); |
||
6613 | leency | 175 | BEGIN |
7597 | akron1 | 176 | IF isByte(n) THEN |
177 | OutByte(Byte(n)) |
||
178 | ELSE |
||
179 | OutInt(n) |
||
180 | END |
||
181 | END OutIntByte; |
||
6613 | leency | 182 | |
7597 | akron1 | 183 | |
184 | PROCEDURE shift* (op, reg: INTEGER); |
||
6613 | leency | 185 | BEGIN |
7597 | akron1 | 186 | CASE op OF |
7693 | akron1 | 187 | |IL.opASR, IL.opASR1, IL.opASR2: OutByte(0F8H + reg) |
188 | |IL.opROR, IL.opROR1, IL.opROR2: OutByte(0C8H + reg) |
||
189 | |IL.opLSL, IL.opLSL1, IL.opLSL2: OutByte(0E0H + reg) |
||
190 | |IL.opLSR, IL.opLSR1, IL.opLSR2: OutByte(0E8H + reg) |
||
7597 | akron1 | 191 | END |
192 | END shift; |
||
6613 | leency | 193 | |
7597 | akron1 | 194 | |
195 | PROCEDURE mov (reg1, reg2: INTEGER); |
||
6613 | leency | 196 | BEGIN |
7597 | akron1 | 197 | OutByte2(89H, 0C0H + reg2 * 8 + reg1) // mov reg1, reg2 |
198 | END mov; |
||
6613 | leency | 199 | |
7597 | akron1 | 200 | |
201 | PROCEDURE xchg (reg1, reg2: INTEGER); |
||
202 | VAR |
||
203 | regs: SET; |
||
204 | |||
6613 | leency | 205 | BEGIN |
7597 | akron1 | 206 | regs := {reg1, reg2}; |
207 | IF regs = {eax, ecx} THEN |
||
208 | OutByte(91H) // xchg eax, ecx |
||
209 | ELSIF regs = {eax, edx} THEN |
||
210 | OutByte(92H) // xchg eax, edx |
||
211 | ELSIF regs = {ecx, edx} THEN |
||
212 | OutByte2(87H, 0D1H) // xchg ecx, edx |
||
213 | END |
||
214 | END xchg; |
||
6613 | leency | 215 | |
7597 | akron1 | 216 | |
217 | PROCEDURE pop (reg: INTEGER); |
||
6613 | leency | 218 | BEGIN |
7597 | akron1 | 219 | OutByte(58H + reg) // pop reg |
220 | END pop; |
||
6613 | leency | 221 | |
7597 | akron1 | 222 | |
223 | PROCEDURE push (reg: INTEGER); |
||
6613 | leency | 224 | BEGIN |
7597 | akron1 | 225 | OutByte(50H + reg) // push reg |
226 | END push; |
||
6613 | leency | 227 | |
7597 | akron1 | 228 | |
229 | PROCEDURE movrc (reg, n: INTEGER); |
||
6613 | leency | 230 | BEGIN |
7597 | akron1 | 231 | OutByte(0B8H + reg); // mov reg, n |
232 | OutInt(n) |
||
233 | END movrc; |
||
6613 | leency | 234 | |
7597 | akron1 | 235 | |
236 | PROCEDURE pushc (n: INTEGER); |
||
6613 | leency | 237 | BEGIN |
7597 | akron1 | 238 | OutByte(68H + short(n)); // push n |
239 | OutIntByte(n) |
||
240 | END pushc; |
||
6613 | leency | 241 | |
7597 | akron1 | 242 | |
243 | PROCEDURE test (reg: INTEGER); |
||
6613 | leency | 244 | BEGIN |
7597 | akron1 | 245 | OutByte2(85H, 0C0H + reg * 9) // test reg, reg |
246 | END test; |
||
6613 | leency | 247 | |
7597 | akron1 | 248 | |
249 | PROCEDURE neg (reg: INTEGER); |
||
6613 | leency | 250 | BEGIN |
7597 | akron1 | 251 | OutByte2(0F7H, 0D8H + reg) // neg reg |
252 | END neg; |
||
6613 | leency | 253 | |
7597 | akron1 | 254 | |
255 | PROCEDURE not (reg: INTEGER); |
||
6613 | leency | 256 | BEGIN |
7597 | akron1 | 257 | OutByte2(0F7H, 0D0H + reg) // not reg |
258 | END not; |
||
6613 | leency | 259 | |
7597 | akron1 | 260 | |
261 | PROCEDURE add (reg1, reg2: INTEGER); |
||
6613 | leency | 262 | BEGIN |
7597 | akron1 | 263 | OutByte2(01H, 0C0H + reg2 * 8 + reg1) // add reg1, reg2 |
264 | END add; |
||
6613 | leency | 265 | |
7597 | akron1 | 266 | |
267 | PROCEDURE andrc (reg, n: INTEGER); |
||
6613 | leency | 268 | BEGIN |
7597 | akron1 | 269 | OutByte2(81H + short(n), 0E0H + reg); // and reg, n |
270 | OutIntByte(n) |
||
271 | END andrc; |
||
6613 | leency | 272 | |
7597 | akron1 | 273 | |
274 | PROCEDURE orrc (reg, n: INTEGER); |
||
6613 | leency | 275 | BEGIN |
7597 | akron1 | 276 | OutByte2(81H + short(n), 0C8H + reg); // or reg, n |
277 | OutIntByte(n) |
||
278 | END orrc; |
||
6613 | leency | 279 | |
7597 | akron1 | 280 | |
281 | PROCEDURE addrc (reg, n: INTEGER); |
||
6613 | leency | 282 | BEGIN |
7597 | akron1 | 283 | OutByte2(81H + short(n), 0C0H + reg); // add reg, n |
284 | OutIntByte(n) |
||
285 | END addrc; |
||
6613 | leency | 286 | |
7597 | akron1 | 287 | |
288 | PROCEDURE subrc (reg, n: INTEGER); |
||
6613 | leency | 289 | BEGIN |
7597 | akron1 | 290 | OutByte2(81H + short(n), 0E8H + reg); // sub reg, n |
291 | OutIntByte(n) |
||
292 | END subrc; |
||
6613 | leency | 293 | |
7597 | akron1 | 294 | |
295 | PROCEDURE cmprr (reg1, reg2: INTEGER); |
||
6613 | leency | 296 | BEGIN |
7597 | akron1 | 297 | OutByte2(39H, 0C0H + reg2 * 8 + reg1) // cmp reg1, reg2 |
298 | END cmprr; |
||
6613 | leency | 299 | |
7597 | akron1 | 300 | |
301 | PROCEDURE cmprc (reg, n: INTEGER); |
||
6613 | leency | 302 | BEGIN |
7597 | akron1 | 303 | OutByte2(81H + short(n), 0F8H + reg); // cmp reg, n |
304 | OutIntByte(n) |
||
305 | END cmprc; |
||
6613 | leency | 306 | |
7597 | akron1 | 307 | |
308 | PROCEDURE setcc (cond, reg: INTEGER); |
||
6613 | leency | 309 | BEGIN |
7597 | akron1 | 310 | OutByte3(0FH, cond, 0C0H + reg) // setcc reg |
311 | END setcc; |
||
6613 | leency | 312 | |
7597 | akron1 | 313 | |
7667 | akron1 | 314 | PROCEDURE xor (reg1, reg2: INTEGER); |
315 | BEGIN |
||
316 | OutByte2(31H, 0C0H + reg2 * 8 + reg1) // xor reg1, reg2 |
||
317 | END xor; |
||
318 | |||
319 | |||
7597 | akron1 | 320 | PROCEDURE drop; |
6613 | leency | 321 | BEGIN |
7597 | akron1 | 322 | REG.Drop(R) |
323 | END drop; |
||
6613 | leency | 324 | |
7597 | akron1 | 325 | |
7693 | akron1 | 326 | PROCEDURE GetAnyReg (): INTEGER; |
327 | RETURN REG.GetAnyReg(R) |
||
328 | END GetAnyReg; |
||
7597 | akron1 | 329 | |
6613 | leency | 330 | |
7597 | akron1 | 331 | PROCEDURE cond* (op: INTEGER): INTEGER; |
332 | VAR |
||
333 | res: INTEGER; |
||
6613 | leency | 334 | |
335 | BEGIN |
||
7597 | akron1 | 336 | CASE op OF |
7693 | akron1 | 337 | |IL.opGT, IL.opGTC: res := jg |
338 | |IL.opGE, IL.opGEC: res := jge |
||
339 | |IL.opLT, IL.opLTC: res := jl |
||
340 | |IL.opLE, IL.opLEC: res := jle |
||
341 | |IL.opEQ, IL.opEQC: res := je |
||
342 | |IL.opNE, IL.opNEC: res := jne |
||
7597 | akron1 | 343 | END |
6613 | leency | 344 | |
7597 | akron1 | 345 | RETURN res |
346 | END cond; |
||
347 | |||
348 | |||
7693 | akron1 | 349 | PROCEDURE inv0* (op: INTEGER): INTEGER; |
350 | RETURN ORD(BITS(op) / {0}) |
||
351 | END inv0; |
||
6613 | leency | 352 | |
353 | |||
7597 | akron1 | 354 | PROCEDURE Reloc* (op, value: INTEGER); |
355 | VAR |
||
356 | reloc: RELOC; |
||
6613 | leency | 357 | |
358 | BEGIN |
||
7597 | akron1 | 359 | NEW(reloc); |
360 | reloc.op := op; |
||
361 | reloc.value := value; |
||
362 | LISTS.push(CodeList, reloc) |
||
363 | END Reloc; |
||
6613 | leency | 364 | |
365 | |||
7597 | akron1 | 366 | PROCEDURE jcc* (cc, label: INTEGER); |
367 | VAR |
||
368 | j: JCC; |
||
6613 | leency | 369 | |
370 | BEGIN |
||
7597 | akron1 | 371 | NEW(j); |
372 | j.label := label; |
||
373 | j.jmp := cc; |
||
374 | j.short := FALSE; |
||
375 | LISTS.push(CodeList, j) |
||
376 | END jcc; |
||
6613 | leency | 377 | |
378 | |||
7597 | akron1 | 379 | PROCEDURE jmp* (label: INTEGER); |
380 | VAR |
||
381 | j: JMP; |
||
6613 | leency | 382 | |
383 | BEGIN |
||
7597 | akron1 | 384 | NEW(j); |
385 | j.label := label; |
||
386 | j.short := FALSE; |
||
387 | LISTS.push(CodeList, j) |
||
388 | END jmp; |
||
6613 | leency | 389 | |
390 | |||
7597 | akron1 | 391 | PROCEDURE call* (label: INTEGER); |
392 | VAR |
||
393 | c: CALL; |
||
6613 | leency | 394 | |
395 | BEGIN |
||
7597 | akron1 | 396 | NEW(c); |
397 | c.label := label; |
||
398 | c.short := TRUE; |
||
399 | LISTS.push(CodeList, c) |
||
400 | END call; |
||
6613 | leency | 401 | |
402 | |||
7597 | akron1 | 403 | PROCEDURE Pic (reg, opcode, value: INTEGER); |
6613 | leency | 404 | BEGIN |
7597 | akron1 | 405 | OutByte(0E8H); OutInt(0); // call L |
406 | // L: |
||
407 | pop(reg); |
||
408 | OutByte2(081H, 0C0H + reg); // add reg, ... |
||
409 | Reloc(opcode, value) |
||
410 | END Pic; |
||
6613 | leency | 411 | |
412 | |||
7597 | akron1 | 413 | PROCEDURE CallRTL (pic: BOOLEAN; proc: INTEGER); |
414 | VAR |
||
415 | label: INTEGER; |
||
416 | reg1: INTEGER; |
||
6613 | leency | 417 | |
418 | BEGIN |
||
7693 | akron1 | 419 | label := IL.codes.rtl[proc]; |
6613 | leency | 420 | |
7597 | akron1 | 421 | IF label < 0 THEN |
422 | label := -label; |
||
423 | IF pic THEN |
||
7693 | akron1 | 424 | reg1 := GetAnyReg(); |
7597 | akron1 | 425 | Pic(reg1, BIN.PICIMP, label); |
426 | OutByte2(0FFH, 010H + reg1); // call dword[reg1] |
||
427 | drop |
||
428 | ELSE |
||
429 | OutByte2(0FFH, 015H); // call dword[label] |
||
430 | Reloc(BIN.RIMP, label) |
||
431 | END |
||
432 | ELSE |
||
433 | call(label) |
||
434 | END |
||
435 | END CallRTL; |
||
6613 | leency | 436 | |
437 | |||
7597 | akron1 | 438 | PROCEDURE SetLabel* (label: INTEGER); |
439 | VAR |
||
440 | L: LABEL; |
||
6613 | leency | 441 | |
442 | BEGIN |
||
7597 | akron1 | 443 | NEW(L); |
444 | L.label := label; |
||
445 | LISTS.push(CodeList, L) |
||
446 | END SetLabel; |
||
6613 | leency | 447 | |
448 | |||
7597 | akron1 | 449 | PROCEDURE fixup*; |
450 | VAR |
||
451 | code: ANYCODE; |
||
452 | count, i: INTEGER; |
||
453 | shorted: BOOLEAN; |
||
454 | jump: JUMP; |
||
6613 | leency | 455 | |
456 | BEGIN |
||
457 | |||
7597 | akron1 | 458 | REPEAT |
6613 | leency | 459 | |
7597 | akron1 | 460 | shorted := FALSE; |
461 | count := 0; |
||
6613 | leency | 462 | |
7597 | akron1 | 463 | code := CodeList.first(ANYCODE); |
464 | WHILE code # NIL DO |
||
465 | code.offset := count; |
||
6613 | leency | 466 | |
7597 | akron1 | 467 | CASE code OF |
7693 | akron1 | 468 | |CODE: INC(count, code.length) |
7597 | akron1 | 469 | |LABEL: BIN.SetLabel(program, code.label, count) |
470 | |JMP: IF code.short THEN INC(count, 2) ELSE INC(count, 5) END; code.offset := count |
||
471 | |JCC: IF code.short THEN INC(count, 2) ELSE INC(count, 6) END; code.offset := count |
||
472 | |CALL: INC(count, 5); code.offset := count |
||
473 | |RELOC: INC(count, 4) |
||
474 | END; |
||
6613 | leency | 475 | |
7597 | akron1 | 476 | code := code.next(ANYCODE) |
477 | END; |
||
6613 | leency | 478 | |
7597 | akron1 | 479 | code := CodeList.first(ANYCODE); |
480 | WHILE code # NIL DO |
||
6613 | leency | 481 | |
7597 | akron1 | 482 | IF code IS JUMP THEN |
483 | jump := code(JUMP); |
||
484 | jump.diff := BIN.GetLabel(program, jump.label) - code.offset; |
||
485 | IF ~jump.short & isByte(jump.diff) THEN |
||
486 | jump.short := TRUE; |
||
487 | shorted := TRUE |
||
488 | END |
||
489 | END; |
||
6613 | leency | 490 | |
7597 | akron1 | 491 | code := code.next(ANYCODE) |
492 | END |
||
6613 | leency | 493 | |
7597 | akron1 | 494 | UNTIL ~shorted; |
6613 | leency | 495 | |
7597 | akron1 | 496 | code := CodeList.first(ANYCODE); |
497 | WHILE code # NIL DO |
||
6613 | leency | 498 | |
7597 | akron1 | 499 | CASE code OF |
6613 | leency | 500 | |
7693 | akron1 | 501 | |CODE: |
7597 | akron1 | 502 | FOR i := 0 TO code.length - 1 DO |
503 | BIN.PutCode(program, code.code[i]) |
||
504 | END |
||
6613 | leency | 505 | |
7597 | akron1 | 506 | |LABEL: |
507 | BIN.SetLabel(program, code.label, code.offset) |
||
6613 | leency | 508 | |
7597 | akron1 | 509 | |JMP: |
510 | IF code.short THEN |
||
511 | BIN.PutCode(program, 0EBH); |
||
512 | BIN.PutCode(program, Byte(code.diff)) |
||
513 | ELSE |
||
514 | BIN.PutCode(program, 0E9H); |
||
515 | BIN.PutCode32LE(program, code.diff) |
||
516 | END |
||
6613 | leency | 517 | |
7597 | akron1 | 518 | |JCC: |
519 | IF code.short THEN |
||
520 | BIN.PutCode(program, code.jmp - 16); |
||
521 | BIN.PutCode(program, Byte(code.diff)) |
||
522 | ELSE |
||
523 | BIN.PutCode(program, 0FH); |
||
524 | BIN.PutCode(program, code.jmp); |
||
525 | BIN.PutCode32LE(program, code.diff) |
||
526 | END |
||
6613 | leency | 527 | |
7597 | akron1 | 528 | |CALL: |
529 | BIN.PutCode(program, 0E8H); |
||
530 | BIN.PutCode32LE(program, code.diff) |
||
6613 | leency | 531 | |
7597 | akron1 | 532 | |RELOC: |
533 | BIN.PutReloc(program, code.op); |
||
534 | BIN.PutCode32LE(program, code.value) |
||
6613 | leency | 535 | |
7597 | akron1 | 536 | END; |
537 | |||
538 | code := code.next(ANYCODE) |
||
6613 | leency | 539 | END |
540 | |||
7597 | akron1 | 541 | END fixup; |
6613 | leency | 542 | |
543 | |||
7597 | akron1 | 544 | PROCEDURE UnOp (VAR reg: INTEGER); |
6613 | leency | 545 | BEGIN |
7597 | akron1 | 546 | REG.UnOp(R, reg) |
547 | END UnOp; |
||
6613 | leency | 548 | |
549 | |||
7597 | akron1 | 550 | PROCEDURE BinOp (VAR reg1, reg2: INTEGER); |
6613 | leency | 551 | BEGIN |
7597 | akron1 | 552 | REG.BinOp(R, reg1, reg2) |
553 | END BinOp; |
||
6613 | leency | 554 | |
555 | |||
7597 | akron1 | 556 | PROCEDURE PushAll (NumberOfParameters: INTEGER); |
6613 | leency | 557 | BEGIN |
7597 | akron1 | 558 | REG.PushAll(R); |
7693 | akron1 | 559 | DEC(R.pushed, NumberOfParameters) |
7597 | akron1 | 560 | END PushAll; |
6613 | leency | 561 | |
562 | |||
7597 | akron1 | 563 | PROCEDURE NewLabel (): INTEGER; |
6613 | leency | 564 | BEGIN |
7597 | akron1 | 565 | BIN.NewLabel(program) |
7693 | akron1 | 566 | RETURN IL.NewLabel() |
7597 | akron1 | 567 | END NewLabel; |
6613 | leency | 568 | |
569 | |||
7597 | akron1 | 570 | PROCEDURE GetRegA; |
6613 | leency | 571 | BEGIN |
7597 | akron1 | 572 | ASSERT(REG.GetReg(R, eax)) |
573 | END GetRegA; |
||
6613 | leency | 574 | |
575 | |||
7696 | akron1 | 576 | PROCEDURE translate (pic: BOOLEAN; stroffs: INTEGER); |
7597 | akron1 | 577 | VAR |
578 | cmd: COMMAND; |
||
6613 | leency | 579 | |
7597 | akron1 | 580 | reg1, reg2: INTEGER; |
6613 | leency | 581 | |
7597 | akron1 | 582 | n, a, b, label, cc: INTEGER; |
6613 | leency | 583 | |
7693 | akron1 | 584 | opcode, param1, param2: INTEGER; |
6613 | leency | 585 | |
7597 | akron1 | 586 | float: REAL; |
6613 | leency | 587 | |
588 | BEGIN |
||
7696 | akron1 | 589 | cmd := IL.codes.commands.first(COMMAND); |
6613 | leency | 590 | |
7597 | akron1 | 591 | WHILE cmd # NIL DO |
6613 | leency | 592 | |
7597 | akron1 | 593 | param1 := cmd.param1; |
594 | param2 := cmd.param2; |
||
6613 | leency | 595 | |
7693 | akron1 | 596 | opcode := cmd.opcode; |
6613 | leency | 597 | |
7693 | akron1 | 598 | CASE opcode OF |
599 | |||
600 | |IL.opJMP: |
||
7597 | akron1 | 601 | jmp(param1) |
6613 | leency | 602 | |
7693 | akron1 | 603 | |IL.opCALL: |
7597 | akron1 | 604 | call(param1) |
6613 | leency | 605 | |
7693 | akron1 | 606 | |IL.opCALLI: |
7597 | akron1 | 607 | IF pic THEN |
7693 | akron1 | 608 | reg1 := GetAnyReg(); |
7597 | akron1 | 609 | Pic(reg1, BIN.PICIMP, param1); |
610 | OutByte2(0FFH, 010H + reg1); // call dword[reg1] |
||
611 | drop |
||
612 | ELSE |
||
613 | OutByte2(0FFH, 015H); // call dword[L] |
||
614 | Reloc(BIN.RIMP, param1) |
||
615 | END |
||
6613 | leency | 616 | |
7693 | akron1 | 617 | |IL.opCALLP: |
7597 | akron1 | 618 | UnOp(reg1); |
619 | OutByte2(0FFH, 0D0H + reg1); // call reg1 |
||
620 | drop; |
||
621 | ASSERT(R.top = -1) |
||
6613 | leency | 622 | |
7693 | akron1 | 623 | |IL.opPRECALL: |
7597 | akron1 | 624 | n := param2; |
625 | IF (param1 # 0) & (n # 0) THEN |
||
626 | subrc(esp, 8) |
||
627 | END; |
||
628 | WHILE n > 0 DO |
||
629 | subrc(esp, 8); |
||
630 | OutByte3(0DDH, 01CH, 024H); // fstp qword[esp] |
||
631 | DEC(n) |
||
632 | END; |
||
633 | PushAll(0) |
||
6613 | leency | 634 | |
7693 | akron1 | 635 | |IL.opALIGN16: |
7597 | akron1 | 636 | ASSERT(eax IN R.regs); |
637 | mov(eax, esp); |
||
638 | andrc(esp, -16); |
||
639 | n := (3 - param2 MOD 4) * 4; |
||
640 | IF n > 0 THEN |
||
641 | subrc(esp, n) |
||
642 | END; |
||
643 | push(eax) |
||
644 | |||
7693 | akron1 | 645 | |IL.opRES: |
7597 | akron1 | 646 | ASSERT(R.top = -1); |
647 | GetRegA; |
||
648 | n := param2; |
||
649 | WHILE n > 0 DO |
||
650 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
651 | addrc(esp, 8); |
||
652 | DEC(n) |
||
653 | END |
||
654 | |||
7693 | akron1 | 655 | |IL.opRESF: |
7597 | akron1 | 656 | n := param2; |
657 | IF n > 0 THEN |
||
658 | OutByte3(0DDH, 5CH + long(n * 8), 24H); |
||
659 | OutIntByte(n * 8); // fstp qword[esp + n*8] |
||
660 | INC(n) |
||
661 | END; |
||
662 | |||
663 | WHILE n > 0 DO |
||
664 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
665 | addrc(esp, 8); |
||
666 | DEC(n) |
||
667 | END |
||
668 | |||
7693 | akron1 | 669 | |IL.opENTER: |
7597 | akron1 | 670 | ASSERT(R.top = -1); |
671 | |||
672 | SetLabel(param1); |
||
673 | |||
674 | push(ebp); |
||
675 | mov(ebp, esp); |
||
676 | |||
677 | n := param2; |
||
678 | IF n > 4 THEN |
||
679 | movrc(ecx, n); |
||
680 | pushc(0); // @@: push 0 |
||
681 | OutByte2(0E2H, 0FCH) // loop @b |
||
682 | ELSE |
||
683 | WHILE n > 0 DO |
||
684 | pushc(0); |
||
685 | DEC(n) |
||
686 | END |
||
687 | END |
||
688 | |||
7693 | akron1 | 689 | |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: |
690 | IF opcode = IL.opLEAVER THEN |
||
7597 | akron1 | 691 | UnOp(reg1); |
692 | IF reg1 # eax THEN |
||
693 | GetRegA; |
||
694 | ASSERT(REG.Exchange(R, reg1, eax)); |
||
695 | drop |
||
696 | END; |
||
697 | drop |
||
698 | END; |
||
699 | |||
700 | ASSERT(R.top = -1); |
||
701 | |||
7693 | akron1 | 702 | IF param1 > 0 THEN |
703 | mov(esp, ebp) |
||
704 | END; |
||
705 | |||
7597 | akron1 | 706 | pop(ebp); |
707 | |||
708 | n := param2; |
||
709 | IF n > 0 THEN |
||
710 | n := n * 4; |
||
711 | OutByte(0C2H); OutWord(Word(n)) // ret n |
||
712 | ELSE |
||
713 | OutByte(0C3H) // ret |
||
714 | END |
||
715 | |||
7693 | akron1 | 716 | |IL.opPUSHC: |
7597 | akron1 | 717 | pushc(param2) |
718 | |||
7693 | akron1 | 719 | |IL.opPARAM: |
7597 | akron1 | 720 | n := param2; |
721 | IF n = 1 THEN |
||
722 | UnOp(reg1); |
||
723 | push(reg1); |
||
724 | drop |
||
725 | ELSE |
||
726 | ASSERT(R.top + 1 <= n); |
||
727 | PushAll(n) |
||
728 | END |
||
729 | |||
7693 | akron1 | 730 | |IL.opCLEANUP: |
7597 | akron1 | 731 | n := param2 * 4; |
732 | IF n # 0 THEN |
||
733 | addrc(esp, n) |
||
734 | END |
||
735 | |||
7693 | akron1 | 736 | |IL.opPOPSP: |
7597 | akron1 | 737 | pop(esp) |
738 | |||
7693 | akron1 | 739 | |IL.opCONST: |
740 | movrc(GetAnyReg(), param2) |
||
7597 | akron1 | 741 | |
7693 | akron1 | 742 | |IL.opLABEL: |
743 | SetLabel(param1) // L: |
||
7597 | akron1 | 744 | |
7693 | akron1 | 745 | |IL.opNOP: |
7597 | akron1 | 746 | |
7693 | akron1 | 747 | |IL.opGADR: |
748 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 749 | IF pic THEN |
750 | Pic(reg1, BIN.PICBSS, param2) |
||
751 | ELSE |
||
752 | OutByte(0B8H + reg1); // mov reg1, _bss + param2 |
||
753 | Reloc(BIN.RBSS, param2) |
||
754 | END |
||
755 | |||
7693 | akron1 | 756 | |IL.opLADR: |
7597 | akron1 | 757 | n := param2 * 4; |
7693 | akron1 | 758 | OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n)); // lea reg1, dword[ebp + n] |
7597 | akron1 | 759 | OutIntByte(n) |
760 | |||
7693 | akron1 | 761 | |IL.opVADR: |
7597 | akron1 | 762 | n := param2 * 4; |
7693 | akron1 | 763 | OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n)); // mov reg1, dword[ebp + n] |
7597 | akron1 | 764 | OutIntByte(n) |
765 | |||
7693 | akron1 | 766 | |IL.opSADR: |
767 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 768 | IF pic THEN |
769 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
||
770 | ELSE |
||
771 | OutByte(0B8H + reg1); // mov reg1, _data + stroffs + param2 |
||
772 | Reloc(BIN.RDATA, stroffs + param2) |
||
773 | END |
||
774 | |||
7693 | akron1 | 775 | |IL.opSAVEC: |
7597 | akron1 | 776 | UnOp(reg1); |
777 | OutByte2(0C7H, reg1); OutInt(param2); // mov dword[reg1], param2 |
||
778 | drop |
||
779 | |||
7693 | akron1 | 780 | |IL.opSAVE8C: |
7597 | akron1 | 781 | UnOp(reg1); |
782 | OutByte3(0C6H, reg1, Byte(param2)); // mov byte[reg1], param2 |
||
783 | drop |
||
784 | |||
7693 | akron1 | 785 | |IL.opSAVE16C: |
7597 | akron1 | 786 | UnOp(reg1); |
787 | OutByte3(66H, 0C7H, reg1); OutWord(Word(param2)); // mov word[reg1], param2 |
||
788 | drop |
||
789 | |||
7693 | akron1 | 790 | |IL.opVLOAD32: |
7597 | akron1 | 791 | n := param2 * 4; |
7693 | akron1 | 792 | reg1 := GetAnyReg(); |
7597 | akron1 | 793 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
794 | OutIntByte(n); |
||
795 | OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] |
||
796 | |||
7693 | akron1 | 797 | |IL.opGLOAD32: |
798 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 799 | IF pic THEN |
800 | Pic(reg1, BIN.PICBSS, param2); |
||
801 | OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] |
||
802 | ELSE |
||
803 | OutByte2(08BH, 05H + reg1 * 8); // mov reg1, dword[_bss + param2] |
||
804 | Reloc(BIN.RBSS, param2) |
||
805 | END |
||
806 | |||
7693 | akron1 | 807 | |IL.opLLOAD32: |
7597 | akron1 | 808 | n := param2 * 4; |
7693 | akron1 | 809 | OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n)); // mov reg1, dword[ebp + n] |
7597 | akron1 | 810 | OutIntByte(n) |
811 | |||
7693 | akron1 | 812 | |IL.opLOAD32: |
7597 | akron1 | 813 | UnOp(reg1); |
814 | OutByte2(8BH, reg1 * 9) // mov reg1, dword[reg1] |
||
815 | |||
7693 | akron1 | 816 | |IL.opVLOAD8: |
7597 | akron1 | 817 | n := param2 * 4; |
7693 | akron1 | 818 | reg1 := GetAnyReg(); |
7597 | akron1 | 819 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
820 | OutIntByte(n); |
||
821 | OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] |
||
822 | |||
7693 | akron1 | 823 | |IL.opGLOAD8: |
824 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 825 | IF pic THEN |
826 | Pic(reg1, BIN.PICBSS, param2); |
||
827 | OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] |
||
828 | ELSE |
||
829 | OutByte3(00FH, 0B6H, 05H + reg1 * 8); // movzx reg1, byte[_bss + param2] |
||
830 | Reloc(BIN.RBSS, param2) |
||
831 | END |
||
832 | |||
7693 | akron1 | 833 | |IL.opLLOAD8: |
7597 | akron1 | 834 | n := param2 * 4; |
7693 | akron1 | 835 | OutByte3(0FH, 0B6H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, byte[ebp + n] |
7597 | akron1 | 836 | OutIntByte(n) |
837 | |||
7693 | akron1 | 838 | |IL.opLOAD8: |
7597 | akron1 | 839 | UnOp(reg1); |
840 | OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1] |
||
841 | |||
7693 | akron1 | 842 | |IL.opVLOAD16: |
7597 | akron1 | 843 | n := param2 * 4; |
7693 | akron1 | 844 | reg1 := GetAnyReg(); |
7597 | akron1 | 845 | OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n] |
846 | OutIntByte(n); |
||
847 | OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] |
||
848 | |||
7693 | akron1 | 849 | |IL.opGLOAD16: |
850 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 851 | IF pic THEN |
852 | Pic(reg1, BIN.PICBSS, param2); |
||
853 | OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] |
||
854 | ELSE |
||
855 | OutByte3(00FH, 0B7H, 05H + reg1 * 8); // movzx reg1, word[_bss + param2] |
||
856 | Reloc(BIN.RBSS, param2) |
||
857 | END |
||
858 | |||
7693 | akron1 | 859 | |IL.opLLOAD16: |
7597 | akron1 | 860 | n := param2 * 4; |
7693 | akron1 | 861 | OutByte3(0FH, 0B7H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, word[ebp + n] |
7597 | akron1 | 862 | OutIntByte(n) |
863 | |||
7693 | akron1 | 864 | |IL.opLOAD16: |
7597 | akron1 | 865 | UnOp(reg1); |
866 | OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1] |
||
867 | |||
7693 | akron1 | 868 | |IL.opUMINUS: |
7597 | akron1 | 869 | UnOp(reg1); |
870 | neg(reg1) |
||
871 | |||
7693 | akron1 | 872 | |IL.opADD: |
7597 | akron1 | 873 | BinOp(reg1, reg2); |
874 | add(reg1, reg2); |
||
875 | drop |
||
876 | |||
7693 | akron1 | 877 | |IL.opADDL, IL.opADDR: |
7597 | akron1 | 878 | IF param2 # 0 THEN |
879 | UnOp(reg1); |
||
880 | IF param2 = 1 THEN |
||
881 | OutByte(40H + reg1) // inc reg1 |
||
882 | ELSIF param2 = -1 THEN |
||
883 | OutByte(48H + reg1) // dec reg1 |
||
884 | ELSE |
||
885 | addrc(reg1, param2) |
||
886 | END |
||
887 | END |
||
888 | |||
7693 | akron1 | 889 | |IL.opSUB: |
7597 | akron1 | 890 | BinOp(reg1, reg2); |
891 | OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 |
||
892 | drop |
||
893 | |||
7693 | akron1 | 894 | |IL.opSUBR, IL.opSUBL: |
7597 | akron1 | 895 | UnOp(reg1); |
896 | n := param2; |
||
897 | IF n = 1 THEN |
||
898 | OutByte(48H + reg1) // dec reg1 |
||
899 | ELSIF n = -1 THEN |
||
900 | OutByte(40H + reg1) // inc reg1 |
||
901 | ELSIF n # 0 THEN |
||
902 | subrc(reg1, n) |
||
903 | END; |
||
7693 | akron1 | 904 | IF opcode = IL.opSUBL THEN |
7597 | akron1 | 905 | neg(reg1) |
906 | END |
||
907 | |||
7693 | akron1 | 908 | |IL.opMULC: |
7597 | akron1 | 909 | UnOp(reg1); |
910 | |||
911 | a := param2; |
||
912 | IF a > 1 THEN |
||
7693 | akron1 | 913 | n := UTILS.Log2(a) |
7597 | akron1 | 914 | ELSIF a < -1 THEN |
7693 | akron1 | 915 | n := UTILS.Log2(-a) |
7597 | akron1 | 916 | ELSE |
917 | n := -1 |
||
918 | END; |
||
919 | |||
920 | IF a = 1 THEN |
||
921 | |||
922 | ELSIF a = -1 THEN |
||
923 | neg(reg1) |
||
924 | ELSIF a = 0 THEN |
||
7667 | akron1 | 925 | xor(reg1, reg1) |
7597 | akron1 | 926 | ELSE |
927 | IF n > 0 THEN |
||
928 | IF a < 0 THEN |
||
929 | neg(reg1) |
||
930 | END; |
||
931 | |||
932 | IF n # 1 THEN |
||
933 | OutByte3(0C1H, 0E0H + reg1, n) // shl reg1, n |
||
934 | ELSE |
||
935 | OutByte2(0D1H, 0E0H + reg1) // shl reg1, 1 |
||
936 | END |
||
937 | ELSE |
||
938 | OutByte2(69H + short(a), 0C0H + reg1 * 9); // imul reg1, a |
||
939 | OutIntByte(a) |
||
940 | END |
||
941 | END |
||
942 | |||
7693 | akron1 | 943 | |IL.opMUL: |
7597 | akron1 | 944 | BinOp(reg1, reg2); |
945 | OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); // imul reg1, reg2 |
||
946 | drop |
||
947 | |||
7693 | akron1 | 948 | |IL.opSAVE, IL.opSAVE32: |
7597 | akron1 | 949 | BinOp(reg2, reg1); |
950 | OutByte2(89H, reg2 * 8 + reg1); // mov dword[reg1], reg2 |
||
951 | drop; |
||
952 | drop |
||
953 | |||
7693 | akron1 | 954 | |IL.opSAVE8: |
7597 | akron1 | 955 | BinOp(reg2, reg1); |
956 | OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2 |
||
957 | drop; |
||
958 | drop |
||
959 | |||
7693 | akron1 | 960 | |IL.opSAVE16: |
7597 | akron1 | 961 | BinOp(reg2, reg1); |
962 | OutByte3(66H, 89H, reg2 * 8 + reg1); // mov word[reg1], reg2 |
||
963 | drop; |
||
964 | drop |
||
965 | |||
7693 | akron1 | 966 | |IL.opSAVEP: |
7597 | akron1 | 967 | UnOp(reg1); |
968 | IF pic THEN |
||
7693 | akron1 | 969 | reg2 := GetAnyReg(); |
7597 | akron1 | 970 | Pic(reg2, BIN.PICCODE, param2); |
971 | OutByte2(089H, reg2 * 8 + reg1); // mov dword[reg1], reg2 |
||
972 | drop |
||
973 | ELSE |
||
974 | OutByte2(0C7H, reg1); // mov dword[reg1], L |
||
975 | Reloc(BIN.RCODE, param2) |
||
976 | END; |
||
977 | drop |
||
978 | |||
7693 | akron1 | 979 | |IL.opSAVEIP: |
7597 | akron1 | 980 | UnOp(reg1); |
981 | IF pic THEN |
||
7693 | akron1 | 982 | reg2 := GetAnyReg(); |
7597 | akron1 | 983 | Pic(reg2, BIN.PICIMP, param2); |
984 | OutByte2(0FFH, 30H + reg2); // push dword[reg2] |
||
985 | OutByte2(08FH, reg1); // pop dword[reg1] |
||
986 | drop |
||
987 | ELSE |
||
988 | OutByte2(0FFH, 035H); // push dword[L] |
||
989 | Reloc(BIN.RIMP, param2); |
||
990 | OutByte2(08FH, reg1) // pop dword[reg1] |
||
991 | END; |
||
992 | drop |
||
993 | |||
7693 | akron1 | 994 | |IL.opPUSHP: |
995 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 996 | IF pic THEN |
997 | Pic(reg1, BIN.PICCODE, param2) |
||
998 | ELSE |
||
999 | OutByte(0B8H + reg1); // mov reg1, L |
||
1000 | Reloc(BIN.RCODE, param2) |
||
1001 | END |
||
1002 | |||
7693 | akron1 | 1003 | |IL.opPUSHIP: |
1004 | reg1 := GetAnyReg(); |
||
7597 | akron1 | 1005 | IF pic THEN |
1006 | Pic(reg1, BIN.PICIMP, param2); |
||
1007 | OutByte2(08BH, reg1 * 9) // mov reg1, dword[reg1] |
||
1008 | ELSE |
||
1009 | OutByte2(08BH, 05H + reg1 * 8); // mov reg1, dword[L] |
||
1010 | Reloc(BIN.RIMP, param2) |
||
1011 | END |
||
1012 | |||
7693 | akron1 | 1013 | |IL.opNOT: |
7597 | akron1 | 1014 | UnOp(reg1); |
1015 | test(reg1); |
||
1016 | setcc(sete, reg1); |
||
1017 | andrc(reg1, 1) |
||
1018 | |||
7693 | akron1 | 1019 | |IL.opORD: |
7597 | akron1 | 1020 | UnOp(reg1); |
1021 | test(reg1); |
||
1022 | setcc(setne, reg1); |
||
1023 | andrc(reg1, 1) |
||
1024 | |||
7693 | akron1 | 1025 | |IL.opSBOOL: |
7597 | akron1 | 1026 | BinOp(reg2, reg1); |
1027 | test(reg2); |
||
7693 | akron1 | 1028 | OutByte3(0FH, 95H, reg1); // setne byte[reg1] |
7597 | akron1 | 1029 | drop; |
1030 | drop |
||
1031 | |||
7693 | akron1 | 1032 | |IL.opSBOOLC: |
7597 | akron1 | 1033 | UnOp(reg1); |
1034 | OutByte3(0C6H, reg1, ORD(param2 # 0)); // mov byte[reg1], 0/1 |
||
1035 | drop |
||
1036 | |||
7693 | akron1 | 1037 | |IL.opODD: |
7597 | akron1 | 1038 | UnOp(reg1); |
1039 | andrc(reg1, 1) |
||
1040 | |||
7693 | akron1 | 1041 | |IL.opEQ..IL.opGE, |
1042 | IL.opEQC..IL.opGEC: |
||
1043 | |||
1044 | IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN |
||
1045 | BinOp(reg1, reg2); |
||
1046 | cmprr(reg1, reg2); |
||
1047 | drop |
||
7597 | akron1 | 1048 | ELSE |
7693 | akron1 | 1049 | UnOp(reg1); |
1050 | IF param2 = 0 THEN |
||
1051 | test(reg1) |
||
1052 | ELSE |
||
1053 | cmprc(reg1, param2) |
||
1054 | END |
||
7597 | akron1 | 1055 | END; |
1056 | |||
1057 | drop; |
||
7693 | akron1 | 1058 | cc := cond(opcode); |
7597 | akron1 | 1059 | |
7693 | akron1 | 1060 | IF cmd.next(COMMAND).opcode = IL.opJE THEN |
7597 | akron1 | 1061 | label := cmd.next(COMMAND).param1; |
1062 | jcc(cc, label); |
||
1063 | cmd := cmd.next(COMMAND) |
||
1064 | |||
7693 | akron1 | 1065 | ELSIF cmd.next(COMMAND).opcode = IL.opJNE THEN |
7597 | akron1 | 1066 | label := cmd.next(COMMAND).param1; |
7693 | akron1 | 1067 | jcc(inv0(cc), label); |
7597 | akron1 | 1068 | cmd := cmd.next(COMMAND) |
1069 | |||
1070 | ELSE |
||
7693 | akron1 | 1071 | reg1 := GetAnyReg(); |
7597 | akron1 | 1072 | setcc(cc + 16, reg1); |
1073 | andrc(reg1, 1) |
||
1074 | END |
||
1075 | |||
7693 | akron1 | 1076 | |IL.opEQB, IL.opNEB: |
7597 | akron1 | 1077 | BinOp(reg1, reg2); |
1078 | drop; |
||
1079 | |||
1080 | test(reg1); |
||
1081 | OutByte2(74H, 5); // je @f |
||
1082 | movrc(reg1, 1); // mov reg1, 1 |
||
1083 | // @@: |
||
1084 | test(reg2); |
||
1085 | OutByte2(74H, 5); // je @f |
||
1086 | movrc(reg2, 1); // mov reg2, 1 |
||
1087 | // @@: |
||
1088 | |||
1089 | cmprr(reg1, reg2); |
||
7693 | akron1 | 1090 | IF opcode = IL.opEQB THEN |
7597 | akron1 | 1091 | setcc(sete, reg1) |
1092 | ELSE |
||
1093 | setcc(setne, reg1) |
||
1094 | END; |
||
1095 | andrc(reg1, 1) |
||
7693 | akron1 | 1096 | |
1097 | |IL.opACC: |
||
7667 | akron1 | 1098 | IF (R.top # 0) OR (R.stk[0] # eax) THEN |
1099 | PushAll(0); |
||
1100 | GetRegA; |
||
1101 | pop(eax); |
||
1102 | DEC(R.pushed) |
||
1103 | END |
||
7597 | akron1 | 1104 | |
7693 | akron1 | 1105 | |IL.opDROP: |
7597 | akron1 | 1106 | UnOp(reg1); |
1107 | drop |
||
1108 | |||
7693 | akron1 | 1109 | |IL.opJNZ: |
7597 | akron1 | 1110 | UnOp(reg1); |
1111 | test(reg1); |
||
1112 | jcc(jne, param1) |
||
1113 | |||
7693 | akron1 | 1114 | |IL.opJZ: |
7597 | akron1 | 1115 | UnOp(reg1); |
1116 | test(reg1); |
||
1117 | jcc(je, param1) |
||
1118 | |||
7693 | akron1 | 1119 | |IL.opJE: |
7597 | akron1 | 1120 | UnOp(reg1); |
1121 | test(reg1); |
||
1122 | jcc(jne, param1); |
||
7693 | akron1 | 1123 | drop |
7597 | akron1 | 1124 | |
7693 | akron1 | 1125 | |IL.opJNE: |
7597 | akron1 | 1126 | UnOp(reg1); |
1127 | test(reg1); |
||
1128 | jcc(je, param1); |
||
7693 | akron1 | 1129 | drop |
7597 | akron1 | 1130 | |
7693 | akron1 | 1131 | |IL.opSWITCH: |
7597 | akron1 | 1132 | UnOp(reg1); |
1133 | IF param2 = 0 THEN |
||
1134 | reg2 := eax |
||
1135 | ELSE |
||
1136 | reg2 := ecx |
||
1137 | END; |
||
1138 | IF reg1 # reg2 THEN |
||
1139 | ASSERT(REG.GetReg(R, reg2)); |
||
1140 | ASSERT(REG.Exchange(R, reg1, reg2)); |
||
1141 | drop |
||
1142 | END; |
||
1143 | drop |
||
1144 | |||
7693 | akron1 | 1145 | |IL.opENDSW: |
7597 | akron1 | 1146 | |
7693 | akron1 | 1147 | |IL.opCASEL: |
7597 | akron1 | 1148 | cmprc(eax, param1); |
1149 | jcc(jl, param2) |
||
1150 | |||
7693 | akron1 | 1151 | |IL.opCASER: |
7597 | akron1 | 1152 | cmprc(eax, param1); |
1153 | jcc(jg, param2) |
||
1154 | |||
7693 | akron1 | 1155 | |IL.opCASELR: |
7597 | akron1 | 1156 | cmprc(eax, param1); |
1157 | jcc(jl, param2); |
||
1158 | jcc(jg, cmd.param3) |
||
1159 | |||
7693 | akron1 | 1160 | |IL.opCODE: |
7597 | akron1 | 1161 | OutByte(param2) |
1162 | |||
7693 | akron1 | 1163 | |IL.opGET, IL.opGETC: |
1164 | IF opcode = IL.opGET THEN |
||
1165 | BinOp(reg1, reg2) |
||
1166 | ELSIF opcode = IL.opGETC THEN |
||
1167 | UnOp(reg2); |
||
1168 | reg1 := GetAnyReg(); |
||
1169 | movrc(reg1, param1) |
||
1170 | END; |
||
7597 | akron1 | 1171 | drop; |
1172 | drop; |
||
1173 | |||
1174 | CASE param2 OF |
||
1175 | |1: |
||
1176 | OutByte2(8AH, reg1 * 9); // mov reg1, byte[reg1] |
||
1177 | OutByte2(88H, reg1 * 8 + reg2) // mov byte[reg2], reg1 |
||
1178 | |||
1179 | |2: |
||
1180 | OutByte3(66H, 8BH, reg1 * 9); // mov reg1, word[reg1] |
||
1181 | OutByte3(66H, 89H, reg1 * 8 + reg2) // mov word[reg2], reg1 |
||
1182 | |||
1183 | |4: |
||
1184 | OutByte2(8BH, reg1 * 9); // mov reg1, dword[reg1] |
||
1185 | OutByte2(89H, reg1 * 8 + reg2) // mov dword[reg2], reg1 |
||
1186 | |||
1187 | |8: |
||
1188 | PushAll(0); |
||
7696 | akron1 | 1189 | push(reg1); |
7597 | akron1 | 1190 | push(reg2); |
1191 | pushc(8); |
||
7693 | akron1 | 1192 | CallRTL(pic, IL._move) |
7597 | akron1 | 1193 | |
1194 | END |
||
1195 | |||
7693 | akron1 | 1196 | |IL.opSAVES: |
7696 | akron1 | 1197 | UnOp(reg2); |
1198 | REG.PushAll_1(R); |
||
7597 | akron1 | 1199 | |
1200 | IF pic THEN |
||
7696 | akron1 | 1201 | reg1 := GetAnyReg(); |
7597 | akron1 | 1202 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
7696 | akron1 | 1203 | push(reg1); |
1204 | drop |
||
7597 | akron1 | 1205 | ELSE |
1206 | OutByte(068H); // push _data + stroffs + param2 |
||
1207 | Reloc(BIN.RDATA, stroffs + param2); |
||
1208 | END; |
||
1209 | |||
7696 | akron1 | 1210 | push(reg2); |
1211 | drop; |
||
7597 | akron1 | 1212 | pushc(param1); |
7693 | akron1 | 1213 | CallRTL(pic, IL._move) |
7597 | akron1 | 1214 | |
7693 | akron1 | 1215 | |IL.opCHKBYTE: |
7597 | akron1 | 1216 | BinOp(reg1, reg2); |
1217 | cmprc(reg1, 256); |
||
1218 | jcc(jb, param1) |
||
1219 | |||
7693 | akron1 | 1220 | |IL.opCHKIDX: |
7597 | akron1 | 1221 | UnOp(reg1); |
1222 | cmprc(reg1, param2); |
||
1223 | jcc(jb, param1) |
||
1224 | |||
7693 | akron1 | 1225 | |IL.opCHKIDX2: |
7597 | akron1 | 1226 | BinOp(reg1, reg2); |
1227 | IF param2 # -1 THEN |
||
1228 | cmprr(reg2, reg1); |
||
1229 | mov(reg1, reg2); |
||
1230 | drop; |
||
1231 | jcc(jb, param1) |
||
1232 | ELSE |
||
1233 | INCL(R.regs, reg1); |
||
1234 | DEC(R.top); |
||
1235 | R.stk[R.top] := reg2 |
||
1236 | END |
||
1237 | |||
7693 | akron1 | 1238 | |IL.opLEN: |
7597 | akron1 | 1239 | n := param2; |
1240 | UnOp(reg1); |
||
1241 | drop; |
||
1242 | EXCL(R.regs, reg1); |
||
1243 | |||
1244 | WHILE n > 0 DO |
||
1245 | UnOp(reg2); |
||
1246 | drop; |
||
1247 | DEC(n) |
||
1248 | END; |
||
1249 | |||
1250 | INCL(R.regs, reg1); |
||
1251 | ASSERT(REG.GetReg(R, reg1)) |
||
1252 | |||
7693 | akron1 | 1253 | |IL.opINCC: |
7597 | akron1 | 1254 | UnOp(reg1); |
7693 | akron1 | 1255 | OutByte2(81H + short(param2), reg1); OutIntByte(param2); // add dword[reg1], param2 |
7597 | akron1 | 1256 | drop |
1257 | |||
7693 | akron1 | 1258 | |IL.opINC, IL.opDEC: |
7597 | akron1 | 1259 | BinOp(reg1, reg2); |
7693 | akron1 | 1260 | OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); // add/sub dword[reg2], reg1 |
7597 | akron1 | 1261 | drop; |
1262 | drop |
||
1263 | |||
7693 | akron1 | 1264 | |IL.opINCCB, IL.opDECCB: |
7597 | akron1 | 1265 | UnOp(reg1); |
7693 | akron1 | 1266 | OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, Byte(param2)); // add/sub byte[reg1], n |
7597 | akron1 | 1267 | drop |
1268 | |||
7693 | akron1 | 1269 | |IL.opINCB, IL.opDECB: |
7597 | akron1 | 1270 | BinOp(reg1, reg2); |
7693 | akron1 | 1271 | OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); // add/sub byte[reg2], reg1 |
7597 | akron1 | 1272 | drop; |
1273 | drop |
||
1274 | |||
7693 | akron1 | 1275 | |IL.opMULS: |
7597 | akron1 | 1276 | BinOp(reg1, reg2); |
1277 | OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 |
||
1278 | drop |
||
1279 | |||
7693 | akron1 | 1280 | |IL.opMULSC: |
7597 | akron1 | 1281 | UnOp(reg1); |
1282 | andrc(reg1, param2) |
||
1283 | |||
7693 | akron1 | 1284 | |IL.opDIVS: |
7597 | akron1 | 1285 | BinOp(reg1, reg2); |
7667 | akron1 | 1286 | xor(reg1, reg2); |
7597 | akron1 | 1287 | drop |
1288 | |||
7693 | akron1 | 1289 | |IL.opDIVSC: |
7597 | akron1 | 1290 | UnOp(reg1); |
1291 | OutByte2(81H + short(param2), 0F0H + reg1); // xor reg1, n |
||
1292 | OutIntByte(param2) |
||
1293 | |||
7693 | akron1 | 1294 | |IL.opADDS: |
7597 | akron1 | 1295 | BinOp(reg1, reg2); |
1296 | OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2 |
||
1297 | drop |
||
1298 | |||
7693 | akron1 | 1299 | |IL.opSUBS: |
7597 | akron1 | 1300 | BinOp(reg1, reg2); |
1301 | not(reg2); |
||
1302 | OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 |
||
1303 | drop |
||
1304 | |||
7693 | akron1 | 1305 | |IL.opADDSL, IL.opADDSR: |
7597 | akron1 | 1306 | UnOp(reg1); |
1307 | orrc(reg1, param2) |
||
1308 | |||
7693 | akron1 | 1309 | |IL.opSUBSL: |
7597 | akron1 | 1310 | UnOp(reg1); |
1311 | not(reg1); |
||
1312 | andrc(reg1, param2) |
||
1313 | |||
7693 | akron1 | 1314 | |IL.opSUBSR: |
7597 | akron1 | 1315 | UnOp(reg1); |
7693 | akron1 | 1316 | andrc(reg1, ORD(-BITS(param2))) |
7597 | akron1 | 1317 | |
7693 | akron1 | 1318 | |IL.opUMINS: |
7597 | akron1 | 1319 | UnOp(reg1); |
1320 | not(reg1) |
||
1321 | |||
7693 | akron1 | 1322 | |IL.opLENGTH: |
7597 | akron1 | 1323 | PushAll(2); |
7693 | akron1 | 1324 | CallRTL(pic, IL._length); |
7597 | akron1 | 1325 | GetRegA |
1326 | |||
7693 | akron1 | 1327 | |IL.opLENGTHW: |
7597 | akron1 | 1328 | PushAll(2); |
7693 | akron1 | 1329 | CallRTL(pic, IL._lengthw); |
7597 | akron1 | 1330 | GetRegA |
1331 | |||
7693 | akron1 | 1332 | |IL.opCHR: |
7597 | akron1 | 1333 | UnOp(reg1); |
1334 | andrc(reg1, 255) |
||
1335 | |||
7693 | akron1 | 1336 | |IL.opWCHR: |
7597 | akron1 | 1337 | UnOp(reg1); |
1338 | andrc(reg1, 65535) |
||
1339 | |||
7693 | akron1 | 1340 | |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: |
7597 | akron1 | 1341 | UnOp(reg1); |
1342 | IF reg1 # ecx THEN |
||
1343 | ASSERT(REG.GetReg(R, ecx)); |
||
1344 | ASSERT(REG.Exchange(R, reg1, ecx)); |
||
1345 | drop |
||
1346 | END; |
||
1347 | |||
1348 | BinOp(reg1, reg2); |
||
1349 | ASSERT(reg2 = ecx); |
||
1350 | OutByte(0D3H); |
||
7693 | akron1 | 1351 | shift(opcode, reg1); // shift reg1, cl |
7597 | akron1 | 1352 | drop |
1353 | |||
7693 | akron1 | 1354 | |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: |
7597 | akron1 | 1355 | UnOp(reg1); |
1356 | IF reg1 # ecx THEN |
||
1357 | ASSERT(REG.GetReg(R, ecx)); |
||
1358 | ASSERT(REG.Exchange(R, reg1, ecx)); |
||
1359 | drop |
||
1360 | END; |
||
1361 | |||
7693 | akron1 | 1362 | reg1 := GetAnyReg(); |
7597 | akron1 | 1363 | movrc(reg1, param2); |
1364 | BinOp(reg1, reg2); |
||
1365 | ASSERT(reg1 = ecx); |
||
1366 | OutByte(0D3H); |
||
7693 | akron1 | 1367 | shift(opcode, reg2); // shift reg2, cl |
7597 | akron1 | 1368 | drop; |
1369 | drop; |
||
1370 | ASSERT(REG.GetReg(R, reg2)) |
||
1371 | |||
7693 | akron1 | 1372 | |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: |
7597 | akron1 | 1373 | UnOp(reg1); |
7693 | akron1 | 1374 | n := param2 MOD 32; |
7597 | akron1 | 1375 | IF n # 1 THEN |
1376 | OutByte(0C1H) |
||
1377 | ELSE |
||
1378 | OutByte(0D1H) |
||
1379 | END; |
||
7693 | akron1 | 1380 | shift(opcode, reg1); // shift reg1, n |
7597 | akron1 | 1381 | IF n # 1 THEN |
1382 | OutByte(n) |
||
1383 | END |
||
1384 | |||
7693 | akron1 | 1385 | |IL.opMIN: |
7597 | akron1 | 1386 | BinOp(reg1, reg2); |
1387 | cmprr(reg1, reg2); |
||
1388 | OutByte2(07EH, 002H); // jle @f |
||
1389 | mov(reg1, reg2); // mov reg1, reg2 |
||
1390 | // @@: |
||
1391 | drop |
||
1392 | |||
7693 | akron1 | 1393 | |IL.opMAX: |
7597 | akron1 | 1394 | BinOp(reg1, reg2); |
1395 | cmprr(reg1, reg2); |
||
1396 | OutByte2(07DH, 002H); // jge @f |
||
1397 | mov(reg1, reg2); // mov reg1, reg2 |
||
1398 | // @@: |
||
1399 | drop |
||
1400 | |||
7693 | akron1 | 1401 | |IL.opMINC: |
7597 | akron1 | 1402 | UnOp(reg1); |
1403 | cmprc(reg1, param2); |
||
1404 | OutByte2(07EH, 005H); // jle @f |
||
7693 | akron1 | 1405 | movrc(reg1, param2) // mov reg1, param2 |
7597 | akron1 | 1406 | // @@: |
1407 | |||
7693 | akron1 | 1408 | |IL.opMAXC: |
7597 | akron1 | 1409 | UnOp(reg1); |
1410 | cmprc(reg1, param2); |
||
1411 | OutByte2(07DH, 005H); // jge @f |
||
7693 | akron1 | 1412 | movrc(reg1, param2) // mov reg1, param2 |
7597 | akron1 | 1413 | // @@: |
1414 | |||
7693 | akron1 | 1415 | |IL.opIN: |
7597 | akron1 | 1416 | label := NewLabel(); |
1417 | BinOp(reg1, reg2); |
||
1418 | cmprc(reg1, 32); |
||
1419 | OutByte2(72H, 4); // jb L |
||
7667 | akron1 | 1420 | xor(reg1, reg1); |
7597 | akron1 | 1421 | jmp(label); |
1422 | //L: |
||
1423 | OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 |
||
1424 | setcc(setc, reg1); |
||
1425 | andrc(reg1, 1); |
||
1426 | SetLabel(label); |
||
1427 | drop |
||
1428 | |||
7693 | akron1 | 1429 | |IL.opINR: |
7597 | akron1 | 1430 | label := NewLabel(); |
1431 | UnOp(reg1); |
||
7693 | akron1 | 1432 | reg2 := GetAnyReg(); |
7597 | akron1 | 1433 | cmprc(reg1, 32); |
1434 | OutByte2(72H, 4); // jb L |
||
7667 | akron1 | 1435 | xor(reg1, reg1); |
7597 | akron1 | 1436 | jmp(label); |
1437 | //L: |
||
1438 | movrc(reg2, param2); |
||
1439 | OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 |
||
1440 | setcc(setc, reg1); |
||
1441 | andrc(reg1, 1); |
||
1442 | SetLabel(label); |
||
1443 | drop |
||
1444 | |||
7693 | akron1 | 1445 | |IL.opINL: |
7597 | akron1 | 1446 | UnOp(reg1); |
1447 | OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2 |
||
1448 | setcc(setc, reg1); |
||
1449 | andrc(reg1, 1) |
||
1450 | |||
7693 | akron1 | 1451 | |IL.opRSET: |
7597 | akron1 | 1452 | PushAll(2); |
7693 | akron1 | 1453 | CallRTL(pic, IL._set); |
7597 | akron1 | 1454 | GetRegA |
1455 | |||
7693 | akron1 | 1456 | |IL.opRSETR: |
7597 | akron1 | 1457 | PushAll(1); |
1458 | pushc(param2); |
||
7693 | akron1 | 1459 | CallRTL(pic, IL._set); |
7597 | akron1 | 1460 | GetRegA |
1461 | |||
7693 | akron1 | 1462 | |IL.opRSETL: |
7696 | akron1 | 1463 | UnOp(reg1); |
1464 | REG.PushAll_1(R); |
||
7597 | akron1 | 1465 | pushc(param2); |
7696 | akron1 | 1466 | push(reg1); |
1467 | drop; |
||
1468 | CallRTL(pic, IL._set); |
||
7597 | akron1 | 1469 | GetRegA |
1470 | |||
7693 | akron1 | 1471 | |IL.opRSET1: |
7597 | akron1 | 1472 | PushAll(1); |
7696 | akron1 | 1473 | CallRTL(pic, IL._set1); |
7597 | akron1 | 1474 | GetRegA |
1475 | |||
7693 | akron1 | 1476 | |IL.opINCL, IL.opEXCL: |
7597 | akron1 | 1477 | BinOp(reg1, reg2); |
1478 | cmprc(reg1, 32); |
||
1479 | OutByte2(73H, 03H); // jnb L |
||
1480 | OutByte(0FH); |
||
7693 | akron1 | 1481 | IF opcode = IL.opINCL THEN |
7597 | akron1 | 1482 | OutByte(0ABH) // bts dword[reg2], reg1 |
1483 | ELSE |
||
1484 | OutByte(0B3H) // btr dword[reg2], reg1 |
||
1485 | END; |
||
1486 | OutByte(reg2 + 8 * reg1); |
||
1487 | //L: |
||
1488 | drop; |
||
1489 | drop |
||
1490 | |||
7693 | akron1 | 1491 | |IL.opINCLC: |
7597 | akron1 | 1492 | UnOp(reg1); |
1493 | OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2 |
||
1494 | drop |
||
1495 | |||
7693 | akron1 | 1496 | |IL.opEXCLC: |
7597 | akron1 | 1497 | UnOp(reg1); |
1498 | OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2 |
||
1499 | drop |
||
1500 | |||
7693 | akron1 | 1501 | |IL.opDIV: |
7597 | akron1 | 1502 | PushAll(2); |
7696 | akron1 | 1503 | CallRTL(pic, IL._divmod); |
7597 | akron1 | 1504 | GetRegA |
1505 | |||
7693 | akron1 | 1506 | |IL.opDIVR: |
7597 | akron1 | 1507 | a := param2; |
1508 | IF a > 1 THEN |
||
7693 | akron1 | 1509 | n := UTILS.Log2(a) |
7597 | akron1 | 1510 | ELSIF a < -1 THEN |
7693 | akron1 | 1511 | n := UTILS.Log2(-a) |
7597 | akron1 | 1512 | ELSE |
1513 | n := -1 |
||
1514 | END; |
||
1515 | |||
1516 | IF a = 1 THEN |
||
1517 | |||
1518 | ELSIF a = -1 THEN |
||
1519 | UnOp(reg1); |
||
1520 | neg(reg1) |
||
1521 | ELSE |
||
1522 | IF n > 0 THEN |
||
1523 | UnOp(reg1); |
||
1524 | |||
1525 | IF a < 0 THEN |
||
7693 | akron1 | 1526 | reg2 := GetAnyReg(); |
7597 | akron1 | 1527 | mov(reg2, reg1); |
1528 | IF n # 1 THEN |
||
1529 | OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n |
||
1530 | ELSE |
||
1531 | OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 |
||
1532 | END; |
||
1533 | OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 |
||
1534 | drop |
||
1535 | ELSE |
||
1536 | IF n # 1 THEN |
||
1537 | OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n |
||
1538 | ELSE |
||
1539 | OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 |
||
1540 | END |
||
1541 | END |
||
1542 | |||
1543 | ELSE |
||
1544 | PushAll(1); |
||
1545 | pushc(param2); |
||
7696 | akron1 | 1546 | CallRTL(pic, IL._divmod); |
7597 | akron1 | 1547 | GetRegA |
1548 | END |
||
1549 | END |
||
1550 | |||
7693 | akron1 | 1551 | |IL.opDIVL: |
7696 | akron1 | 1552 | UnOp(reg1); |
1553 | REG.PushAll_1(R); |
||
7597 | akron1 | 1554 | pushc(param2); |
7696 | akron1 | 1555 | push(reg1); |
1556 | drop; |
||
1557 | CallRTL(pic, IL._divmod); |
||
7597 | akron1 | 1558 | GetRegA |
1559 | |||
7693 | akron1 | 1560 | |IL.opMOD: |
7597 | akron1 | 1561 | PushAll(2); |
7696 | akron1 | 1562 | CallRTL(pic, IL._divmod); |
1563 | mov(eax, edx); |
||
7597 | akron1 | 1564 | GetRegA |
1565 | |||
7693 | akron1 | 1566 | |IL.opMODR: |
7597 | akron1 | 1567 | a := param2; |
1568 | IF a > 1 THEN |
||
7693 | akron1 | 1569 | n := UTILS.Log2(a) |
7597 | akron1 | 1570 | ELSIF a < -1 THEN |
7693 | akron1 | 1571 | n := UTILS.Log2(-a) |
7597 | akron1 | 1572 | ELSE |
1573 | n := -1 |
||
1574 | END; |
||
1575 | |||
1576 | IF ABS(a) = 1 THEN |
||
1577 | UnOp(reg1); |
||
7667 | akron1 | 1578 | xor(reg1, reg1) |
7597 | akron1 | 1579 | ELSE |
1580 | IF n > 0 THEN |
||
1581 | UnOp(reg1); |
||
1582 | andrc(reg1, ABS(a) - 1); |
||
1583 | |||
1584 | IF a < 0 THEN |
||
1585 | test(reg1); |
||
1586 | OutByte(74H); // je @f |
||
1587 | IF isByte(a) THEN |
||
1588 | OutByte(3) |
||
1589 | ELSE |
||
1590 | OutByte(6) |
||
1591 | END; |
||
1592 | addrc(reg1, a) |
||
1593 | // @@: |
||
1594 | END |
||
1595 | |||
1596 | ELSE |
||
1597 | PushAll(1); |
||
1598 | pushc(param2); |
||
7696 | akron1 | 1599 | CallRTL(pic, IL._divmod); |
1600 | mov(eax, edx); |
||
7597 | akron1 | 1601 | GetRegA |
1602 | END |
||
1603 | END |
||
1604 | |||
7693 | akron1 | 1605 | |IL.opMODL: |
7696 | akron1 | 1606 | UnOp(reg1); |
1607 | REG.PushAll_1(R); |
||
7597 | akron1 | 1608 | pushc(param2); |
7696 | akron1 | 1609 | push(reg1); |
1610 | drop; |
||
1611 | CallRTL(pic, IL._divmod); |
||
1612 | mov(eax, edx); |
||
7597 | akron1 | 1613 | GetRegA |
1614 | |||
7693 | akron1 | 1615 | |IL.opERR: |
1616 | CallRTL(pic, IL._error) |
||
7597 | akron1 | 1617 | |
7693 | akron1 | 1618 | |IL.opABS: |
7597 | akron1 | 1619 | UnOp(reg1); |
1620 | test(reg1); |
||
1621 | OutByte2(07DH, 002H); // jge @f |
||
7693 | akron1 | 1622 | neg(reg1) // neg reg1 |
7597 | akron1 | 1623 | // @@: |
1624 | |||
7693 | akron1 | 1625 | |IL.opCOPY: |
7597 | akron1 | 1626 | PushAll(2); |
1627 | pushc(param2); |
||
7696 | akron1 | 1628 | CallRTL(pic, IL._move) |
7597 | akron1 | 1629 | |
7693 | akron1 | 1630 | |IL.opMOVE: |
7597 | akron1 | 1631 | PushAll(3); |
7696 | akron1 | 1632 | CallRTL(pic, IL._move) |
7597 | akron1 | 1633 | |
7693 | akron1 | 1634 | |IL.opCOPYA: |
7597 | akron1 | 1635 | PushAll(4); |
1636 | pushc(param2); |
||
7693 | akron1 | 1637 | CallRTL(pic, IL._arrcpy); |
7597 | akron1 | 1638 | GetRegA |
1639 | |||
7693 | akron1 | 1640 | |IL.opCOPYS: |
7597 | akron1 | 1641 | PushAll(4); |
1642 | pushc(param2); |
||
7693 | akron1 | 1643 | CallRTL(pic, IL._strcpy) |
7597 | akron1 | 1644 | |
7693 | akron1 | 1645 | |IL.opROT: |
7597 | akron1 | 1646 | PushAll(0); |
1647 | push(esp); |
||
1648 | pushc(param2); |
||
7693 | akron1 | 1649 | CallRTL(pic, IL._rot) |
7597 | akron1 | 1650 | |
7693 | akron1 | 1651 | |IL.opNEW: |
7597 | akron1 | 1652 | PushAll(1); |
1653 | n := param2 + 8; |
||
7693 | akron1 | 1654 | ASSERT(UTILS.Align(n, 32)); |
7597 | akron1 | 1655 | pushc(n); |
1656 | pushc(param1); |
||
7693 | akron1 | 1657 | CallRTL(pic, IL._new) |
7597 | akron1 | 1658 | |
7693 | akron1 | 1659 | |IL.opDISP: |
7597 | akron1 | 1660 | PushAll(1); |
7693 | akron1 | 1661 | CallRTL(pic, IL._dispose) |
7597 | akron1 | 1662 | |
7693 | akron1 | 1663 | |IL.opEQS .. IL.opGES: |
7597 | akron1 | 1664 | PushAll(4); |
7693 | akron1 | 1665 | pushc(opcode - IL.opEQS); |
1666 | CallRTL(pic, IL._strcmp); |
||
7597 | akron1 | 1667 | GetRegA |
1668 | |||
7693 | akron1 | 1669 | |IL.opEQSW .. IL.opGESW: |
7597 | akron1 | 1670 | PushAll(4); |
7693 | akron1 | 1671 | pushc(opcode - IL.opEQSW); |
1672 | CallRTL(pic, IL._strcmpw); |
||
7597 | akron1 | 1673 | GetRegA |
1674 | |||
7693 | akron1 | 1675 | |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP: |
7597 | akron1 | 1676 | UnOp(reg1); |
7693 | akron1 | 1677 | CASE opcode OF |
1678 | |IL.opEQP, IL.opNEP: |
||
7597 | akron1 | 1679 | IF pic THEN |
7693 | akron1 | 1680 | reg2 := GetAnyReg(); |
7597 | akron1 | 1681 | Pic(reg2, BIN.PICCODE, param1); |
1682 | cmprr(reg1, reg2); |
||
1683 | drop |
||
1684 | ELSE |
||
1685 | OutByte2(081H, 0F8H + reg1); // cmp reg1, L |
||
1686 | Reloc(BIN.RCODE, param1) |
||
1687 | END |
||
1688 | |||
7693 | akron1 | 1689 | |IL.opEQIP, IL.opNEIP: |
7597 | akron1 | 1690 | IF pic THEN |
7693 | akron1 | 1691 | reg2 := GetAnyReg(); |
7597 | akron1 | 1692 | Pic(reg2, BIN.PICIMP, param1); |
1693 | OutByte2(03BH, reg1 * 8 + reg2); //cmp reg1, dword [reg2] |
||
1694 | drop |
||
1695 | ELSE |
||
1696 | OutByte2(3BH, 05H + reg1 * 8); // cmp reg1, dword[L] |
||
1697 | Reloc(BIN.RIMP, param1) |
||
1698 | END |
||
1699 | |||
1700 | END; |
||
1701 | drop; |
||
7693 | akron1 | 1702 | reg1 := GetAnyReg(); |
7597 | akron1 | 1703 | |
7693 | akron1 | 1704 | CASE opcode OF |
1705 | |IL.opEQP, IL.opEQIP: setcc(sete, reg1) |
||
1706 | |IL.opNEP, IL.opNEIP: setcc(setne, reg1) |
||
7597 | akron1 | 1707 | END; |
1708 | |||
1709 | andrc(reg1, 1) |
||
1710 | |||
7693 | akron1 | 1711 | |IL.opPUSHT: |
7597 | akron1 | 1712 | UnOp(reg1); |
7693 | akron1 | 1713 | reg2 := GetAnyReg(); |
7597 | akron1 | 1714 | OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH) // mov reg2, dword[reg1 - 4] |
1715 | |||
7693 | akron1 | 1716 | |IL.opISREC: |
7597 | akron1 | 1717 | PushAll(2); |
7693 | akron1 | 1718 | pushc(param2 * tcount); |
1719 | CallRTL(pic, IL._isrec); |
||
7597 | akron1 | 1720 | GetRegA |
1721 | |||
7693 | akron1 | 1722 | |IL.opIS: |
7597 | akron1 | 1723 | PushAll(1); |
7693 | akron1 | 1724 | pushc(param2 * tcount); |
1725 | CallRTL(pic, IL._is); |
||
7597 | akron1 | 1726 | GetRegA |
1727 | |||
7693 | akron1 | 1728 | |IL.opTYPEGR: |
7597 | akron1 | 1729 | PushAll(1); |
7693 | akron1 | 1730 | pushc(param2 * tcount); |
1731 | CallRTL(pic, IL._guardrec); |
||
7597 | akron1 | 1732 | GetRegA |
1733 | |||
7693 | akron1 | 1734 | |IL.opTYPEGP: |
7597 | akron1 | 1735 | UnOp(reg1); |
1736 | PushAll(0); |
||
1737 | push(reg1); |
||
7693 | akron1 | 1738 | pushc(param2 * tcount); |
1739 | CallRTL(pic, IL._guard); |
||
7597 | akron1 | 1740 | GetRegA |
1741 | |||
7693 | akron1 | 1742 | |IL.opTYPEGD: |
7597 | akron1 | 1743 | UnOp(reg1); |
1744 | PushAll(0); |
||
1745 | OutByte3(0FFH, 070H + reg1, 0FCH); // push dword[reg1 - 4] |
||
7693 | akron1 | 1746 | pushc(param2 * tcount); |
1747 | CallRTL(pic, IL._guardrec); |
||
7597 | akron1 | 1748 | GetRegA |
1749 | |||
7693 | akron1 | 1750 | |IL.opCASET: |
7597 | akron1 | 1751 | push(ecx); |
1752 | push(ecx); |
||
7693 | akron1 | 1753 | pushc(param2 * tcount); |
1754 | CallRTL(pic, IL._guardrec); |
||
7597 | akron1 | 1755 | pop(ecx); |
1756 | test(eax); |
||
1757 | jcc(jne, param1) |
||
1758 | |||
7693 | akron1 | 1759 | |IL.opPACK: |
7597 | akron1 | 1760 | BinOp(reg1, reg2); |
1761 | push(reg2); |
||
1762 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1763 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1764 | OutByte2(0D9H, 0FDH); // fscale |
||
1765 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1766 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
1767 | pop(reg2); |
||
1768 | drop; |
||
1769 | drop |
||
1770 | |||
7693 | akron1 | 1771 | |IL.opPACKC: |
7597 | akron1 | 1772 | UnOp(reg1); |
1773 | pushc(param2); |
||
1774 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1775 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1776 | OutByte2(0D9H, 0FDH); // fscale |
||
1777 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1778 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
1779 | pop(reg1); |
||
1780 | drop |
||
1781 | |||
7693 | akron1 | 1782 | |IL.opUNPK: |
7597 | akron1 | 1783 | BinOp(reg1, reg2); |
1784 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1785 | OutByte2(0D9H, 0F4H); // fxtract |
||
1786 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1787 | OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] |
||
1788 | drop; |
||
1789 | drop |
||
1790 | |||
7693 | akron1 | 1791 | |IL.opPUSHF: |
7597 | akron1 | 1792 | subrc(esp, 8); |
1793 | OutByte3(0DDH, 01CH, 024H) // fstp qword[esp] |
||
1794 | |||
7693 | akron1 | 1795 | |IL.opLOADF: |
7597 | akron1 | 1796 | UnOp(reg1); |
1797 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1798 | drop |
||
1799 | |||
7693 | akron1 | 1800 | |IL.opCONSTF: |
7597 | akron1 | 1801 | float := cmd.float; |
1802 | IF float = 0.0 THEN |
||
1803 | OutByte2(0D9H, 0EEH) // fldz |
||
1804 | ELSIF float = 1.0 THEN |
||
1805 | OutByte2(0D9H, 0E8H) // fld1 |
||
1806 | ELSIF float = -1.0 THEN |
||
1807 | OutByte2(0D9H, 0E8H); // fld1 |
||
1808 | OutByte2(0D9H, 0E0H) // fchs |
||
1809 | ELSE |
||
1810 | n := UTILS.splitf(float, a, b); |
||
1811 | pushc(b); |
||
1812 | pushc(a); |
||
1813 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
1814 | addrc(esp, 8) |
||
1815 | END |
||
1816 | |||
7693 | akron1 | 1817 | |IL.opSAVEF: |
7597 | akron1 | 1818 | UnOp(reg1); |
1819 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1820 | drop |
||
1821 | |||
7693 | akron1 | 1822 | |IL.opADDF, IL.opADDFI: |
7597 | akron1 | 1823 | OutByte2(0DEH, 0C1H) // faddp st1, st |
1824 | |||
7693 | akron1 | 1825 | |IL.opSUBF: |
7597 | akron1 | 1826 | OutByte2(0DEH, 0E9H) // fsubp st1, st |
1827 | |||
7693 | akron1 | 1828 | |IL.opSUBFI: |
7597 | akron1 | 1829 | OutByte2(0DEH, 0E1H) // fsubrp st1, st |
1830 | |||
7693 | akron1 | 1831 | |IL.opMULF: |
7597 | akron1 | 1832 | OutByte2(0DEH, 0C9H) // fmulp st1, st |
1833 | |||
7693 | akron1 | 1834 | |IL.opDIVF: |
7597 | akron1 | 1835 | OutByte2(0DEH, 0F9H) // fdivp st1, st |
1836 | |||
7693 | akron1 | 1837 | |IL.opDIVFI: |
7597 | akron1 | 1838 | OutByte2(0DEH, 0F1H) // fdivrp st1, st |
1839 | |||
7693 | akron1 | 1840 | |IL.opUMINF: |
7597 | akron1 | 1841 | OutByte2(0D9H, 0E0H) // fchs |
1842 | |||
7693 | akron1 | 1843 | |IL.opFABS: |
7597 | akron1 | 1844 | OutByte2(0D9H, 0E1H) // fabs |
1845 | |||
7693 | akron1 | 1846 | |IL.opFLT: |
7597 | akron1 | 1847 | UnOp(reg1); |
1848 | push(reg1); |
||
1849 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1850 | pop(reg1); |
||
1851 | drop |
||
1852 | |||
7693 | akron1 | 1853 | |IL.opFLOOR: |
7597 | akron1 | 1854 | subrc(esp, 8); |
1855 | OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); // fstcw word[esp+4] |
||
1856 | OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); // fstcw word[esp+6] |
||
1857 | OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); // and word[esp+4], 1111001111111111b |
||
1858 | OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); // or word[esp+4], 0000010000000000b |
||
1859 | OutByte2(0D9H, 06CH); OutByte2(024H, 004H); // fldcw word[esp+4] |
||
1860 | OutByte2(0D9H, 0FCH); // frndint |
||
1861 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
7693 | akron1 | 1862 | pop(GetAnyReg()); |
7597 | akron1 | 1863 | OutByte2(0D9H, 06CH); OutByte2(024H, 002H); // fldcw word[esp+2] |
1864 | addrc(esp, 4) |
||
1865 | |||
7693 | akron1 | 1866 | |IL.opEQF: |
7597 | akron1 | 1867 | GetRegA; |
1868 | OutByte2(0DAH, 0E9H); // fucompp |
||
1869 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1870 | OutByte(09EH); // sahf |
||
1871 | movrc(eax, 0); |
||
1872 | OutByte2(07AH, 003H); // jp L |
||
1873 | setcc(sete, al) |
||
1874 | // L: |
||
1875 | |||
7693 | akron1 | 1876 | |IL.opNEF: |
7597 | akron1 | 1877 | GetRegA; |
1878 | OutByte2(0DAH, 0E9H); // fucompp |
||
1879 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1880 | OutByte(09EH); // sahf |
||
1881 | movrc(eax, 0); |
||
1882 | OutByte2(07AH, 003H); // jp L |
||
1883 | setcc(setne, al) |
||
1884 | // L: |
||
1885 | |||
7693 | akron1 | 1886 | |IL.opLTF: |
7597 | akron1 | 1887 | GetRegA; |
1888 | OutByte2(0DAH, 0E9H); // fucompp |
||
1889 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1890 | OutByte(09EH); // sahf |
||
1891 | movrc(eax, 0); |
||
1892 | OutByte2(07AH, 00EH); // jp L |
||
1893 | setcc(setc, al); |
||
1894 | setcc(sete, ah); |
||
1895 | test(eax); |
||
1896 | setcc(sete, al); |
||
1897 | andrc(eax, 1) |
||
1898 | // L: |
||
1899 | |||
7693 | akron1 | 1900 | |IL.opGTF: |
7597 | akron1 | 1901 | GetRegA; |
1902 | OutByte2(0DAH, 0E9H); // fucompp |
||
1903 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1904 | OutByte(09EH); // sahf |
||
1905 | movrc(eax, 0); |
||
1906 | OutByte2(07AH, 00FH); // jp L |
||
1907 | setcc(setc, al); |
||
1908 | setcc(sete, ah); |
||
1909 | cmprc(eax, 1); |
||
1910 | setcc(sete, al); |
||
1911 | andrc(eax, 1) |
||
1912 | // L: |
||
1913 | |||
7693 | akron1 | 1914 | |IL.opLEF: |
7597 | akron1 | 1915 | GetRegA; |
1916 | OutByte2(0DAH, 0E9H); // fucompp |
||
1917 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1918 | OutByte(09EH); // sahf |
||
1919 | movrc(eax, 0); |
||
1920 | OutByte2(07AH, 003H); // jp L |
||
1921 | setcc(setnc, al) |
||
1922 | // L: |
||
1923 | |||
7693 | akron1 | 1924 | |IL.opGEF: |
7597 | akron1 | 1925 | GetRegA; |
1926 | OutByte2(0DAH, 0E9H); // fucompp |
||
1927 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1928 | OutByte(09EH); // sahf |
||
1929 | movrc(eax, 0); |
||
1930 | OutByte2(07AH, 010H); // jp L |
||
1931 | setcc(setc, al); |
||
1932 | setcc(sete, ah); |
||
1933 | OutByte2(000H, 0E0H); // add al,ah |
||
1934 | OutByte2(03CH, 001H); // cmp al,1 |
||
1935 | setcc(sete, al); |
||
1936 | andrc(eax, 1) |
||
1937 | // L: |
||
1938 | |||
7693 | akron1 | 1939 | |IL.opINF: |
7597 | akron1 | 1940 | pushc(7FF00000H); |
1941 | pushc(0); |
||
1942 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
1943 | addrc(esp, 8) |
||
1944 | |||
7693 | akron1 | 1945 | |IL.opLADR_UNPK: |
7597 | akron1 | 1946 | n := param2 * 4; |
7693 | akron1 | 1947 | reg1 := GetAnyReg(); |
7597 | akron1 | 1948 | OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] |
1949 | OutIntByte(n); |
||
1950 | BinOp(reg1, reg2); |
||
1951 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1952 | OutByte2(0D9H, 0F4H); // fxtract |
||
1953 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1954 | OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] |
||
1955 | drop; |
||
1956 | drop |
||
1957 | |||
7693 | akron1 | 1958 | |IL.opSADR_PARAM: |
7597 | akron1 | 1959 | IF pic THEN |
7693 | akron1 | 1960 | reg1 := GetAnyReg(); |
7597 | akron1 | 1961 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
1962 | push(reg1); |
||
1963 | drop |
||
1964 | ELSE |
||
1965 | OutByte(068H); // push _data + stroffs + param2 |
||
1966 | Reloc(BIN.RDATA, stroffs + param2) |
||
1967 | END |
||
1968 | |||
7693 | akron1 | 1969 | |IL.opVADR_PARAM: |
7597 | akron1 | 1970 | n := param2 * 4; |
1971 | OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] |
||
1972 | OutIntByte(n) |
||
1973 | |||
7693 | akron1 | 1974 | |IL.opCONST_PARAM: |
7597 | akron1 | 1975 | pushc(param2) |
1976 | |||
7693 | akron1 | 1977 | |IL.opGLOAD32_PARAM: |
7597 | akron1 | 1978 | IF pic THEN |
7693 | akron1 | 1979 | reg1 := GetAnyReg(); |
7597 | akron1 | 1980 | Pic(reg1, BIN.PICBSS, param2); |
1981 | OutByte2(0FFH, 30H + reg1); // push dword[reg1] |
||
1982 | drop |
||
1983 | ELSE |
||
1984 | OutByte2(0FFH, 035H); // push dword[_bss + param2] |
||
1985 | Reloc(BIN.RBSS, param2) |
||
1986 | END |
||
1987 | |||
7693 | akron1 | 1988 | |IL.opLLOAD32_PARAM: |
7597 | akron1 | 1989 | n := param2 * 4; |
1990 | OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] |
||
1991 | OutIntByte(n) |
||
1992 | |||
7693 | akron1 | 1993 | |IL.opLOAD32_PARAM: |
7597 | akron1 | 1994 | UnOp(reg1); |
1995 | OutByte2(0FFH, 30H + reg1); // push dword[reg1] |
||
1996 | drop |
||
1997 | |||
7693 | akron1 | 1998 | |IL.opGADR_SAVEC: |
7597 | akron1 | 1999 | IF pic THEN |
7693 | akron1 | 2000 | reg1 := GetAnyReg(); |
7597 | akron1 | 2001 | Pic(reg1, BIN.PICBSS, param1); |
2002 | OutByte2(0C7H, reg1); // mov dword[reg1], param2 |
||
2003 | OutInt(param2); |
||
2004 | drop |
||
2005 | ELSE |
||
7693 | akron1 | 2006 | OutByte2(0C7H, 05H); // mov dword[_bss + param1], param2 |
7597 | akron1 | 2007 | Reloc(BIN.RBSS, param1); |
2008 | OutInt(param2) |
||
2009 | END |
||
2010 | |||
7693 | akron1 | 2011 | |IL.opLADR_SAVEC: |
7597 | akron1 | 2012 | n := param1 * 4; |
2013 | OutByte2(0C7H, 45H + long(n)); // mov dword[ebp + n], param2 |
||
2014 | OutIntByte(n); |
||
2015 | OutInt(param2) |
||
2016 | |||
7693 | akron1 | 2017 | |IL.opLADR_SAVE: |
7597 | akron1 | 2018 | n := param2 * 4; |
2019 | UnOp(reg1); |
||
2020 | OutByte2(89H, 45H + reg1 * 8 + long(n)); // mov dword[ebp + n], reg1 |
||
2021 | OutIntByte(n); |
||
2022 | drop |
||
2023 | |||
7693 | akron1 | 2024 | |IL.opLADR_INCC: |
7597 | akron1 | 2025 | n := param1 * 4; |
7693 | akron1 | 2026 | IF ABS(param2) = 1 THEN |
2027 | OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); // inc/dec dword[ebp + n] |
||
2028 | OutIntByte(n) |
||
2029 | ELSE |
||
2030 | OutByte2(81H + short(param2), 45H + long(n)); // add dword[ebp + n], param2 |
||
2031 | OutIntByte(n); |
||
2032 | OutIntByte(param2) |
||
2033 | END |
||
7597 | akron1 | 2034 | |
7693 | akron1 | 2035 | |IL.opLADR_INCCB, IL.opLADR_DECCB: |
7597 | akron1 | 2036 | n := param1 * 4; |
7693 | akron1 | 2037 | IF param2 = 1 THEN |
2038 | OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n)); // inc/dec byte[ebp + n] |
||
2039 | OutIntByte(n) |
||
2040 | ELSE |
||
2041 | OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); // add/sub byte[ebp + n], param2 |
||
2042 | OutIntByte(n); |
||
2043 | OutByte(param2 MOD 256) |
||
2044 | END |
||
7597 | akron1 | 2045 | |
7693 | akron1 | 2046 | |IL.opLADR_INC, IL.opLADR_DEC: |
7597 | akron1 | 2047 | n := param2 * 4; |
2048 | UnOp(reg1); |
||
7693 | akron1 | 2049 | OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); // add/sub dword[ebp + n], reg1 |
7597 | akron1 | 2050 | OutIntByte(n); |
2051 | drop |
||
2052 | |||
7693 | akron1 | 2053 | |IL.opLADR_INCB, IL.opLADR_DECB: |
7597 | akron1 | 2054 | n := param2 * 4; |
2055 | UnOp(reg1); |
||
7693 | akron1 | 2056 | OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); // add/sub byte[ebp + n], reg1 |
7597 | akron1 | 2057 | OutIntByte(n); |
2058 | drop |
||
2059 | |||
7693 | akron1 | 2060 | |IL.opLADR_INCL, IL.opLADR_EXCL: |
7597 | akron1 | 2061 | n := param2 * 4; |
2062 | UnOp(reg1); |
||
2063 | cmprc(reg1, 32); |
||
2064 | label := NewLabel(); |
||
2065 | jcc(jnb, label); |
||
7693 | akron1 | 2066 | OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1 |
7597 | akron1 | 2067 | OutIntByte(n); |
2068 | SetLabel(label); |
||
2069 | drop |
||
2070 | |||
7693 | akron1 | 2071 | |IL.opLADR_INCLC, IL.opLADR_EXCLC: |
7597 | akron1 | 2072 | n := param1 * 4; |
7693 | akron1 | 2073 | OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2 |
7597 | akron1 | 2074 | OutIntByte(n); |
2075 | OutByte(param2) |
||
2076 | |||
7693 | akron1 | 2077 | |IL.opLOOP, IL.opENDLOOP: |
7597 | akron1 | 2078 | |
6613 | leency | 2079 | END; |
7597 | akron1 | 2080 | |
2081 | cmd := cmd.next(COMMAND) |
||
6613 | leency | 2082 | END; |
2083 | |||
7597 | akron1 | 2084 | ASSERT(R.pushed = 0); |
2085 | ASSERT(R.top = -1) |
||
6613 | leency | 2086 | |
7597 | akron1 | 2087 | END translate; |
6613 | leency | 2088 | |
2089 | |||
7696 | akron1 | 2090 | PROCEDURE prolog (pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER); |
7597 | akron1 | 2091 | VAR |
7696 | akron1 | 2092 | reg1, entry, L, dcount: INTEGER; |
6613 | leency | 2093 | |
7597 | akron1 | 2094 | BEGIN |
6613 | leency | 2095 | |
7597 | akron1 | 2096 | entry := NewLabel(); |
2097 | SetLabel(entry); |
||
6613 | leency | 2098 | |
7597 | akron1 | 2099 | IF target = mConst.Target_iDLL THEN |
2100 | push(ebp); |
||
2101 | mov(ebp, esp); |
||
2102 | OutByte3(0FFH, 75H, 16); // push dword[ebp+16] |
||
2103 | OutByte3(0FFH, 75H, 12); // push dword[ebp+12] |
||
2104 | OutByte3(0FFH, 75H, 8); // push dword[ebp+8] |
||
7693 | akron1 | 2105 | CallRTL(pic, IL._dllentry); |
7597 | akron1 | 2106 | test(eax); |
2107 | jcc(je, dllret) |
||
2108 | ELSIF target = mConst.Target_iObject THEN |
||
2109 | SetLabel(dllinit) |
||
2110 | END; |
||
6613 | leency | 2111 | |
7597 | akron1 | 2112 | IF target = mConst.Target_iKolibri THEN |
7693 | akron1 | 2113 | reg1 := GetAnyReg(); |
7597 | akron1 | 2114 | Pic(reg1, BIN.IMPTAB, 0); |
2115 | push(reg1); // push IMPORT |
||
2116 | drop |
||
2117 | ELSIF target = mConst.Target_iObject THEN |
||
2118 | OutByte(68H); // push IMPORT |
||
2119 | Reloc(BIN.IMPTAB, 0) |
||
2120 | ELSIF target = mConst.Target_iELF32 THEN |
||
2121 | push(esp) |
||
2122 | ELSE |
||
2123 | pushc(0) |
||
7667 | akron1 | 2124 | END; |
2125 | |||
7597 | akron1 | 2126 | IF pic THEN |
7693 | akron1 | 2127 | reg1 := GetAnyReg(); |
7597 | akron1 | 2128 | Pic(reg1, BIN.PICCODE, entry); |
2129 | push(reg1); // push CODE |
||
2130 | drop |
||
2131 | ELSE |
||
2132 | OutByte(68H); // push CODE |
||
2133 | Reloc(BIN.RCODE, entry) |
||
2134 | END; |
||
6613 | leency | 2135 | |
7597 | akron1 | 2136 | IF pic THEN |
7693 | akron1 | 2137 | reg1 := GetAnyReg(); |
7597 | akron1 | 2138 | Pic(reg1, BIN.PICDATA, 0); |
2139 | push(reg1); // push _data |
||
2140 | drop |
||
2141 | ELSE |
||
2142 | OutByte(68H); // push _data |
||
2143 | Reloc(BIN.RDATA, 0) |
||
2144 | END; |
||
6613 | leency | 2145 | |
7696 | akron1 | 2146 | dcount := CHL.Length(IL.codes.data); |
6613 | leency | 2147 | |
7597 | akron1 | 2148 | pushc(tcount); |
6613 | leency | 2149 | |
7597 | akron1 | 2150 | IF pic THEN |
7693 | akron1 | 2151 | reg1 := GetAnyReg(); |
7597 | akron1 | 2152 | Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); |
2153 | push(reg1); // push _data + tcount * 4 + dcount |
||
2154 | drop |
||
2155 | ELSE |
||
2156 | OutByte(68H); // push _data |
||
2157 | Reloc(BIN.RDATA, tcount * 4 + dcount) |
||
2158 | END; |
||
6613 | leency | 2159 | |
7696 | akron1 | 2160 | CallRTL(pic, IL._init); |
2161 | |||
2162 | IF target = mConst.Target_iELF32 THEN |
||
2163 | L := NewLabel(); |
||
2164 | pushc(0); |
||
2165 | push(esp); |
||
2166 | pushc(1024 * 1024 * stack); |
||
2167 | pushc(0); |
||
2168 | CallRTL(pic, IL._new); |
||
2169 | pop(eax); |
||
2170 | test(eax); |
||
2171 | jcc(je, L); |
||
2172 | addrc(eax, 1024 * 1024 * stack - 4); |
||
2173 | mov(esp, eax); |
||
2174 | SetLabel(L) |
||
2175 | END |
||
7597 | akron1 | 2176 | END prolog; |
6613 | leency | 2177 | |
2178 | |||
7696 | akron1 | 2179 | PROCEDURE epilog (pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER); |
7597 | akron1 | 2180 | VAR |
7693 | akron1 | 2181 | exp: IL.EXPORT_PROC; |
7597 | akron1 | 2182 | path, name, ext: PATHS.PATH; |
6613 | leency | 2183 | |
7693 | akron1 | 2184 | dcount, i: INTEGER; |
6613 | leency | 2185 | |
7597 | akron1 | 2186 | |
2187 | PROCEDURE import (imp: LISTS.LIST); |
||
2188 | VAR |
||
7693 | akron1 | 2189 | lib: IL.IMPORT_LIB; |
2190 | proc: IL.IMPORT_PROC; |
||
7597 | akron1 | 2191 | |
2192 | BEGIN |
||
2193 | |||
7693 | akron1 | 2194 | lib := imp.first(IL.IMPORT_LIB); |
7597 | akron1 | 2195 | WHILE lib # NIL DO |
2196 | BIN.Import(program, lib.name, 0); |
||
7693 | akron1 | 2197 | proc := lib.procs.first(IL.IMPORT_PROC); |
7597 | akron1 | 2198 | WHILE proc # NIL DO |
2199 | BIN.Import(program, proc.name, proc.label); |
||
7693 | akron1 | 2200 | proc := proc.next(IL.IMPORT_PROC) |
7597 | akron1 | 2201 | END; |
7693 | akron1 | 2202 | lib := lib.next(IL.IMPORT_LIB) |
7597 | akron1 | 2203 | END |
2204 | |||
2205 | END import; |
||
2206 | |||
2207 | |||
6613 | leency | 2208 | BEGIN |
2209 | |||
7597 | akron1 | 2210 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN |
2211 | pushc(0); |
||
7693 | akron1 | 2212 | CallRTL(pic, IL._exit); |
7597 | akron1 | 2213 | ELSIF target = mConst.Target_iDLL THEN |
2214 | SetLabel(dllret); |
||
2215 | movrc(eax, 1); |
||
2216 | OutByte(0C9H); // leave |
||
2217 | OutByte3(0C2H, 0CH, 0) // ret 12 |
||
2218 | ELSIF target = mConst.Target_iObject THEN |
||
2219 | movrc(eax, 1); |
||
2220 | OutByte(0C3H) // ret |
||
7693 | akron1 | 2221 | ELSIF target = mConst.Target_iELFSO32 THEN |
2222 | OutByte(0C3H); // ret |
||
2223 | SetLabel(sofinit); |
||
2224 | CallRTL(pic, IL._sofinit); |
||
2225 | OutByte(0C3H) // ret |
||
7597 | akron1 | 2226 | END; |
6613 | leency | 2227 | |
7597 | akron1 | 2228 | fixup; |
2229 | |||
7696 | akron1 | 2230 | dcount := CHL.Length(IL.codes.data); |
7597 | akron1 | 2231 | |
2232 | FOR i := 0 TO tcount - 1 DO |
||
7696 | akron1 | 2233 | BIN.PutData32LE(program, CHL.GetInt(IL.codes.types, i)) |
6613 | leency | 2234 | END; |
2235 | |||
7597 | akron1 | 2236 | FOR i := 0 TO dcount - 1 DO |
7696 | akron1 | 2237 | BIN.PutData(program, CHL.GetByte(IL.codes.data, i)) |
6613 | leency | 2238 | END; |
2239 | |||
7597 | akron1 | 2240 | program.modname := CHL.Length(program.data); |
6613 | leency | 2241 | |
7597 | akron1 | 2242 | PATHS.split(modname, path, name, ext); |
2243 | BIN.PutDataStr(program, name); |
||
2244 | BIN.PutDataStr(program, ext); |
||
2245 | BIN.PutData(program, 0); |
||
6613 | leency | 2246 | |
7597 | akron1 | 2247 | IF target = mConst.Target_iObject THEN |
2248 | BIN.Export(program, "lib_init", dllinit); |
||
2249 | END; |
||
6613 | leency | 2250 | |
7696 | akron1 | 2251 | exp := IL.codes.export.first(IL.EXPORT_PROC); |
7597 | akron1 | 2252 | WHILE exp # NIL DO |
2253 | BIN.Export(program, exp.name, exp.label); |
||
7693 | akron1 | 2254 | exp := exp.next(IL.EXPORT_PROC) |
6613 | leency | 2255 | END; |
2256 | |||
7696 | akron1 | 2257 | import(IL.codes.import); |
6613 | leency | 2258 | |
7696 | akron1 | 2259 | IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4))); |
6613 | leency | 2260 | |
7696 | akron1 | 2261 | BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)); |
7597 | akron1 | 2262 | |
2263 | END epilog; |
||
2264 | |||
2265 | |||
7696 | akron1 | 2266 | PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); |
7597 | akron1 | 2267 | VAR |
7693 | akron1 | 2268 | dllret, dllinit, sofinit: INTEGER; |
2269 | opt: PROG.OPTIONS; |
||
7597 | akron1 | 2270 | |
6613 | leency | 2271 | BEGIN |
7696 | akron1 | 2272 | tcount := CHL.Length(IL.codes.types); |
6613 | leency | 2273 | |
7693 | akron1 | 2274 | opt := options; |
7597 | akron1 | 2275 | CodeList := LISTS.create(NIL); |
2276 | |||
7696 | akron1 | 2277 | program := BIN.create(IL.codes.lcount); |
7597 | akron1 | 2278 | |
2279 | dllinit := NewLabel(); |
||
2280 | dllret := NewLabel(); |
||
7693 | akron1 | 2281 | sofinit := NewLabel(); |
7597 | akron1 | 2282 | |
2283 | IF target = mConst.Target_iObject THEN |
||
7693 | akron1 | 2284 | opt.pic := FALSE |
6613 | leency | 2285 | END; |
7597 | akron1 | 2286 | |
7693 | akron1 | 2287 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32, mConst.Target_iELFSO32} THEN |
2288 | opt.pic := TRUE |
||
7597 | akron1 | 2289 | END; |
2290 | |||
7693 | akron1 | 2291 | REG.Init(R, push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); |
7597 | akron1 | 2292 | |
7696 | akron1 | 2293 | prolog(opt.pic, target, opt.stack, dllinit, dllret); |
2294 | translate(opt.pic, tcount * 4); |
||
2295 | epilog(opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit); |
||
7597 | akron1 | 2296 | |
2297 | BIN.fixup(program); |
||
2298 | |||
2299 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN |
||
7696 | akron1 | 2300 | PE32.write(program, outname, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE) |
7597 | akron1 | 2301 | ELSIF target = mConst.Target_iKolibri THEN |
2302 | KOS.write(program, outname) |
||
2303 | ELSIF target = mConst.Target_iObject THEN |
||
7693 | akron1 | 2304 | MSCOFF.write(program, outname, opt.version) |
2305 | ELSIF target IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN |
||
2306 | ELF.write(program, outname, sofinit, target = mConst.Target_iELFSO32, FALSE) |
||
6613 | leency | 2307 | END |
2308 | |||
7597 | akron1 | 2309 | END CodeGen; |
7209 | akron1 | 2310 | |
7597 | akron1 | 2311 | |
2312 | PROCEDURE SetProgram* (prog: BIN.PROGRAM); |
||
7209 | akron1 | 2313 | BEGIN |
7597 | akron1 | 2314 | program := prog; |
2315 | CodeList := LISTS.create(NIL) |
||
2316 | END SetProgram; |
||
2317 | |||
2318 | |||
7696 | akron1 | 2319 | END X86.>>>>=>=>>>=>>=>=>=>=>> |