Rev 7667 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7597 | akron1 | 1 | (* |
2 | BSD 2-Clause License |
||
6613 | leency | 3 | |
7597 | akron1 | 4 | Copyright (c) 2018, 2019, Anton Krotov |
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 | |||
7693 | akron1 | 576 | PROCEDURE translate (code: IL.CODES; 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 |
||
7597 | akron1 | 589 | cmd := code.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); |
||
1189 | push(reg2); |
||
1190 | push(reg1); |
||
1191 | pushc(8); |
||
7693 | akron1 | 1192 | CallRTL(pic, IL._move) |
7597 | akron1 | 1193 | |
1194 | END |
||
1195 | |||
7693 | akron1 | 1196 | |IL.opSAVES: |
7597 | akron1 | 1197 | UnOp(reg1); |
1198 | drop; |
||
1199 | PushAll(0); |
||
1200 | push(reg1); |
||
1201 | |||
1202 | IF pic THEN |
||
1203 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
||
1204 | push(reg1) |
||
1205 | ELSE |
||
1206 | OutByte(068H); // push _data + stroffs + param2 |
||
1207 | Reloc(BIN.RDATA, stroffs + param2); |
||
1208 | END; |
||
1209 | |||
1210 | pushc(param1); |
||
7693 | akron1 | 1211 | CallRTL(pic, IL._move) |
7597 | akron1 | 1212 | |
7693 | akron1 | 1213 | |IL.opCHKBYTE: |
7597 | akron1 | 1214 | BinOp(reg1, reg2); |
1215 | cmprc(reg1, 256); |
||
1216 | jcc(jb, param1) |
||
1217 | |||
7693 | akron1 | 1218 | |IL.opCHKIDX: |
7597 | akron1 | 1219 | UnOp(reg1); |
1220 | cmprc(reg1, param2); |
||
1221 | jcc(jb, param1) |
||
1222 | |||
7693 | akron1 | 1223 | |IL.opCHKIDX2: |
7597 | akron1 | 1224 | BinOp(reg1, reg2); |
1225 | IF param2 # -1 THEN |
||
1226 | cmprr(reg2, reg1); |
||
1227 | mov(reg1, reg2); |
||
1228 | drop; |
||
1229 | jcc(jb, param1) |
||
1230 | ELSE |
||
1231 | INCL(R.regs, reg1); |
||
1232 | DEC(R.top); |
||
1233 | R.stk[R.top] := reg2 |
||
1234 | END |
||
1235 | |||
7693 | akron1 | 1236 | |IL.opLEN: |
7597 | akron1 | 1237 | n := param2; |
1238 | UnOp(reg1); |
||
1239 | drop; |
||
1240 | EXCL(R.regs, reg1); |
||
1241 | |||
1242 | WHILE n > 0 DO |
||
1243 | UnOp(reg2); |
||
1244 | drop; |
||
1245 | DEC(n) |
||
1246 | END; |
||
1247 | |||
1248 | INCL(R.regs, reg1); |
||
1249 | ASSERT(REG.GetReg(R, reg1)) |
||
1250 | |||
7693 | akron1 | 1251 | |IL.opINCC: |
7597 | akron1 | 1252 | UnOp(reg1); |
7693 | akron1 | 1253 | OutByte2(81H + short(param2), reg1); OutIntByte(param2); // add dword[reg1], param2 |
7597 | akron1 | 1254 | drop |
1255 | |||
7693 | akron1 | 1256 | |IL.opINC, IL.opDEC: |
7597 | akron1 | 1257 | BinOp(reg1, reg2); |
7693 | akron1 | 1258 | OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); // add/sub dword[reg2], reg1 |
7597 | akron1 | 1259 | drop; |
1260 | drop |
||
1261 | |||
7693 | akron1 | 1262 | |IL.opINCCB, IL.opDECCB: |
7597 | akron1 | 1263 | UnOp(reg1); |
7693 | akron1 | 1264 | OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, Byte(param2)); // add/sub byte[reg1], n |
7597 | akron1 | 1265 | drop |
1266 | |||
7693 | akron1 | 1267 | |IL.opINCB, IL.opDECB: |
7597 | akron1 | 1268 | BinOp(reg1, reg2); |
7693 | akron1 | 1269 | OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); // add/sub byte[reg2], reg1 |
7597 | akron1 | 1270 | drop; |
1271 | drop |
||
1272 | |||
7693 | akron1 | 1273 | |IL.opMULS: |
7597 | akron1 | 1274 | BinOp(reg1, reg2); |
1275 | OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 |
||
1276 | drop |
||
1277 | |||
7693 | akron1 | 1278 | |IL.opMULSC: |
7597 | akron1 | 1279 | UnOp(reg1); |
1280 | andrc(reg1, param2) |
||
1281 | |||
7693 | akron1 | 1282 | |IL.opDIVS: |
7597 | akron1 | 1283 | BinOp(reg1, reg2); |
7667 | akron1 | 1284 | xor(reg1, reg2); |
7597 | akron1 | 1285 | drop |
1286 | |||
7693 | akron1 | 1287 | |IL.opDIVSC: |
7597 | akron1 | 1288 | UnOp(reg1); |
1289 | OutByte2(81H + short(param2), 0F0H + reg1); // xor reg1, n |
||
1290 | OutIntByte(param2) |
||
1291 | |||
7693 | akron1 | 1292 | |IL.opADDS: |
7597 | akron1 | 1293 | BinOp(reg1, reg2); |
1294 | OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2 |
||
1295 | drop |
||
1296 | |||
7693 | akron1 | 1297 | |IL.opSUBS: |
7597 | akron1 | 1298 | BinOp(reg1, reg2); |
1299 | not(reg2); |
||
1300 | OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2 |
||
1301 | drop |
||
1302 | |||
7693 | akron1 | 1303 | |IL.opADDSL, IL.opADDSR: |
7597 | akron1 | 1304 | UnOp(reg1); |
1305 | orrc(reg1, param2) |
||
1306 | |||
7693 | akron1 | 1307 | |IL.opSUBSL: |
7597 | akron1 | 1308 | UnOp(reg1); |
1309 | not(reg1); |
||
1310 | andrc(reg1, param2) |
||
1311 | |||
7693 | akron1 | 1312 | |IL.opSUBSR: |
7597 | akron1 | 1313 | UnOp(reg1); |
7693 | akron1 | 1314 | andrc(reg1, ORD(-BITS(param2))) |
7597 | akron1 | 1315 | |
7693 | akron1 | 1316 | |IL.opUMINS: |
7597 | akron1 | 1317 | UnOp(reg1); |
1318 | not(reg1) |
||
1319 | |||
7693 | akron1 | 1320 | |IL.opLENGTH: |
7597 | akron1 | 1321 | PushAll(2); |
7693 | akron1 | 1322 | CallRTL(pic, IL._length); |
7597 | akron1 | 1323 | GetRegA |
1324 | |||
7693 | akron1 | 1325 | |IL.opLENGTHW: |
7597 | akron1 | 1326 | PushAll(2); |
7693 | akron1 | 1327 | CallRTL(pic, IL._lengthw); |
7597 | akron1 | 1328 | GetRegA |
1329 | |||
7693 | akron1 | 1330 | |IL.opCHR: |
7597 | akron1 | 1331 | UnOp(reg1); |
1332 | andrc(reg1, 255) |
||
1333 | |||
7693 | akron1 | 1334 | |IL.opWCHR: |
7597 | akron1 | 1335 | UnOp(reg1); |
1336 | andrc(reg1, 65535) |
||
1337 | |||
7693 | akron1 | 1338 | |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: |
7597 | akron1 | 1339 | UnOp(reg1); |
1340 | IF reg1 # ecx THEN |
||
1341 | ASSERT(REG.GetReg(R, ecx)); |
||
1342 | ASSERT(REG.Exchange(R, reg1, ecx)); |
||
1343 | drop |
||
1344 | END; |
||
1345 | |||
1346 | BinOp(reg1, reg2); |
||
1347 | ASSERT(reg2 = ecx); |
||
1348 | OutByte(0D3H); |
||
7693 | akron1 | 1349 | shift(opcode, reg1); // shift reg1, cl |
7597 | akron1 | 1350 | drop |
1351 | |||
7693 | akron1 | 1352 | |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: |
7597 | akron1 | 1353 | UnOp(reg1); |
1354 | IF reg1 # ecx THEN |
||
1355 | ASSERT(REG.GetReg(R, ecx)); |
||
1356 | ASSERT(REG.Exchange(R, reg1, ecx)); |
||
1357 | drop |
||
1358 | END; |
||
1359 | |||
7693 | akron1 | 1360 | reg1 := GetAnyReg(); |
7597 | akron1 | 1361 | movrc(reg1, param2); |
1362 | BinOp(reg1, reg2); |
||
1363 | ASSERT(reg1 = ecx); |
||
1364 | OutByte(0D3H); |
||
7693 | akron1 | 1365 | shift(opcode, reg2); // shift reg2, cl |
7597 | akron1 | 1366 | drop; |
1367 | drop; |
||
1368 | ASSERT(REG.GetReg(R, reg2)) |
||
1369 | |||
7693 | akron1 | 1370 | |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: |
7597 | akron1 | 1371 | UnOp(reg1); |
7693 | akron1 | 1372 | n := param2 MOD 32; |
7597 | akron1 | 1373 | IF n # 1 THEN |
1374 | OutByte(0C1H) |
||
1375 | ELSE |
||
1376 | OutByte(0D1H) |
||
1377 | END; |
||
7693 | akron1 | 1378 | shift(opcode, reg1); // shift reg1, n |
7597 | akron1 | 1379 | IF n # 1 THEN |
1380 | OutByte(n) |
||
1381 | END |
||
1382 | |||
7693 | akron1 | 1383 | |IL.opMIN: |
7597 | akron1 | 1384 | BinOp(reg1, reg2); |
1385 | cmprr(reg1, reg2); |
||
1386 | OutByte2(07EH, 002H); // jle @f |
||
1387 | mov(reg1, reg2); // mov reg1, reg2 |
||
1388 | // @@: |
||
1389 | drop |
||
1390 | |||
7693 | akron1 | 1391 | |IL.opMAX: |
7597 | akron1 | 1392 | BinOp(reg1, reg2); |
1393 | cmprr(reg1, reg2); |
||
1394 | OutByte2(07DH, 002H); // jge @f |
||
1395 | mov(reg1, reg2); // mov reg1, reg2 |
||
1396 | // @@: |
||
1397 | drop |
||
1398 | |||
7693 | akron1 | 1399 | |IL.opMINC: |
7597 | akron1 | 1400 | UnOp(reg1); |
1401 | cmprc(reg1, param2); |
||
1402 | OutByte2(07EH, 005H); // jle @f |
||
7693 | akron1 | 1403 | movrc(reg1, param2) // mov reg1, param2 |
7597 | akron1 | 1404 | // @@: |
1405 | |||
7693 | akron1 | 1406 | |IL.opMAXC: |
7597 | akron1 | 1407 | UnOp(reg1); |
1408 | cmprc(reg1, param2); |
||
1409 | OutByte2(07DH, 005H); // jge @f |
||
7693 | akron1 | 1410 | movrc(reg1, param2) // mov reg1, param2 |
7597 | akron1 | 1411 | // @@: |
1412 | |||
7693 | akron1 | 1413 | |IL.opIN: |
7597 | akron1 | 1414 | label := NewLabel(); |
1415 | BinOp(reg1, reg2); |
||
1416 | cmprc(reg1, 32); |
||
1417 | OutByte2(72H, 4); // jb L |
||
7667 | akron1 | 1418 | xor(reg1, reg1); |
7597 | akron1 | 1419 | jmp(label); |
1420 | //L: |
||
1421 | OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 |
||
1422 | setcc(setc, reg1); |
||
1423 | andrc(reg1, 1); |
||
1424 | SetLabel(label); |
||
1425 | drop |
||
1426 | |||
7693 | akron1 | 1427 | |IL.opINR: |
7597 | akron1 | 1428 | label := NewLabel(); |
1429 | UnOp(reg1); |
||
7693 | akron1 | 1430 | reg2 := GetAnyReg(); |
7597 | akron1 | 1431 | cmprc(reg1, 32); |
1432 | OutByte2(72H, 4); // jb L |
||
7667 | akron1 | 1433 | xor(reg1, reg1); |
7597 | akron1 | 1434 | jmp(label); |
1435 | //L: |
||
1436 | movrc(reg2, param2); |
||
1437 | OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1 |
||
1438 | setcc(setc, reg1); |
||
1439 | andrc(reg1, 1); |
||
1440 | SetLabel(label); |
||
1441 | drop |
||
1442 | |||
7693 | akron1 | 1443 | |IL.opINL: |
7597 | akron1 | 1444 | UnOp(reg1); |
1445 | OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2 |
||
1446 | setcc(setc, reg1); |
||
1447 | andrc(reg1, 1) |
||
1448 | |||
7693 | akron1 | 1449 | |IL.opRSET: |
7597 | akron1 | 1450 | PushAll(2); |
7693 | akron1 | 1451 | CallRTL(pic, IL._set); |
7597 | akron1 | 1452 | GetRegA |
1453 | |||
7693 | akron1 | 1454 | |IL.opRSETR: |
7597 | akron1 | 1455 | PushAll(1); |
1456 | pushc(param2); |
||
7693 | akron1 | 1457 | CallRTL(pic, IL._set); |
7597 | akron1 | 1458 | GetRegA |
1459 | |||
7693 | akron1 | 1460 | |IL.opRSETL: |
7597 | akron1 | 1461 | PushAll(1); |
1462 | pushc(param2); |
||
7693 | akron1 | 1463 | CallRTL(pic, IL._set2); |
7597 | akron1 | 1464 | GetRegA |
1465 | |||
7693 | akron1 | 1466 | |IL.opRSET1: |
7597 | akron1 | 1467 | UnOp(reg1); |
1468 | PushAll(1); |
||
1469 | push(reg1); |
||
7693 | akron1 | 1470 | CallRTL(pic, IL._set); |
7597 | akron1 | 1471 | GetRegA |
1472 | |||
7693 | akron1 | 1473 | |IL.opINCL, IL.opEXCL: |
7597 | akron1 | 1474 | BinOp(reg1, reg2); |
1475 | cmprc(reg1, 32); |
||
1476 | OutByte2(73H, 03H); // jnb L |
||
1477 | OutByte(0FH); |
||
7693 | akron1 | 1478 | IF opcode = IL.opINCL THEN |
7597 | akron1 | 1479 | OutByte(0ABH) // bts dword[reg2], reg1 |
1480 | ELSE |
||
1481 | OutByte(0B3H) // btr dword[reg2], reg1 |
||
1482 | END; |
||
1483 | OutByte(reg2 + 8 * reg1); |
||
1484 | //L: |
||
1485 | drop; |
||
1486 | drop |
||
1487 | |||
7693 | akron1 | 1488 | |IL.opINCLC: |
7597 | akron1 | 1489 | UnOp(reg1); |
1490 | OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2 |
||
1491 | drop |
||
1492 | |||
7693 | akron1 | 1493 | |IL.opEXCLC: |
7597 | akron1 | 1494 | UnOp(reg1); |
1495 | OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2 |
||
1496 | drop |
||
1497 | |||
7693 | akron1 | 1498 | |IL.opDIV: |
7597 | akron1 | 1499 | PushAll(2); |
7693 | akron1 | 1500 | CallRTL(pic, IL._div); |
7597 | akron1 | 1501 | GetRegA |
1502 | |||
7693 | akron1 | 1503 | |IL.opDIVR: |
7597 | akron1 | 1504 | a := param2; |
1505 | IF a > 1 THEN |
||
7693 | akron1 | 1506 | n := UTILS.Log2(a) |
7597 | akron1 | 1507 | ELSIF a < -1 THEN |
7693 | akron1 | 1508 | n := UTILS.Log2(-a) |
7597 | akron1 | 1509 | ELSE |
1510 | n := -1 |
||
1511 | END; |
||
1512 | |||
1513 | IF a = 1 THEN |
||
1514 | |||
1515 | ELSIF a = -1 THEN |
||
1516 | UnOp(reg1); |
||
1517 | neg(reg1) |
||
1518 | ELSE |
||
1519 | IF n > 0 THEN |
||
1520 | UnOp(reg1); |
||
1521 | |||
1522 | IF a < 0 THEN |
||
7693 | akron1 | 1523 | reg2 := GetAnyReg(); |
7597 | akron1 | 1524 | mov(reg2, reg1); |
1525 | IF n # 1 THEN |
||
1526 | OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n |
||
1527 | ELSE |
||
1528 | OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 |
||
1529 | END; |
||
1530 | OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2 |
||
1531 | drop |
||
1532 | ELSE |
||
1533 | IF n # 1 THEN |
||
1534 | OutByte3(0C1H, 0F8H + reg1, n) // sar reg1, n |
||
1535 | ELSE |
||
1536 | OutByte2(0D1H, 0F8H + reg1) // sar reg1, 1 |
||
1537 | END |
||
1538 | END |
||
1539 | |||
1540 | ELSE |
||
1541 | PushAll(1); |
||
1542 | pushc(param2); |
||
7693 | akron1 | 1543 | CallRTL(pic, IL._div); |
7597 | akron1 | 1544 | GetRegA |
1545 | END |
||
1546 | END |
||
1547 | |||
7693 | akron1 | 1548 | |IL.opDIVL: |
7597 | akron1 | 1549 | PushAll(1); |
1550 | pushc(param2); |
||
7693 | akron1 | 1551 | CallRTL(pic, IL._div2); |
7597 | akron1 | 1552 | GetRegA |
1553 | |||
7693 | akron1 | 1554 | |IL.opMOD: |
7597 | akron1 | 1555 | PushAll(2); |
7693 | akron1 | 1556 | CallRTL(pic, IL._mod); |
7597 | akron1 | 1557 | GetRegA |
1558 | |||
7693 | akron1 | 1559 | |IL.opMODR: |
7597 | akron1 | 1560 | a := param2; |
1561 | IF a > 1 THEN |
||
7693 | akron1 | 1562 | n := UTILS.Log2(a) |
7597 | akron1 | 1563 | ELSIF a < -1 THEN |
7693 | akron1 | 1564 | n := UTILS.Log2(-a) |
7597 | akron1 | 1565 | ELSE |
1566 | n := -1 |
||
1567 | END; |
||
1568 | |||
1569 | IF ABS(a) = 1 THEN |
||
1570 | UnOp(reg1); |
||
7667 | akron1 | 1571 | xor(reg1, reg1) |
7597 | akron1 | 1572 | ELSE |
1573 | IF n > 0 THEN |
||
1574 | UnOp(reg1); |
||
1575 | andrc(reg1, ABS(a) - 1); |
||
1576 | |||
1577 | IF a < 0 THEN |
||
1578 | test(reg1); |
||
1579 | OutByte(74H); // je @f |
||
1580 | IF isByte(a) THEN |
||
1581 | OutByte(3) |
||
1582 | ELSE |
||
1583 | OutByte(6) |
||
1584 | END; |
||
1585 | addrc(reg1, a) |
||
1586 | // @@: |
||
1587 | END |
||
1588 | |||
1589 | ELSE |
||
1590 | PushAll(1); |
||
1591 | pushc(param2); |
||
7693 | akron1 | 1592 | CallRTL(pic, IL._mod); |
7597 | akron1 | 1593 | GetRegA |
1594 | END |
||
1595 | END |
||
1596 | |||
7693 | akron1 | 1597 | |IL.opMODL: |
7597 | akron1 | 1598 | PushAll(1); |
1599 | pushc(param2); |
||
7693 | akron1 | 1600 | CallRTL(pic, IL._mod2); |
7597 | akron1 | 1601 | GetRegA |
1602 | |||
7693 | akron1 | 1603 | |IL.opERR: |
1604 | CallRTL(pic, IL._error) |
||
7597 | akron1 | 1605 | |
7693 | akron1 | 1606 | |IL.opABS: |
7597 | akron1 | 1607 | UnOp(reg1); |
1608 | test(reg1); |
||
1609 | OutByte2(07DH, 002H); // jge @f |
||
7693 | akron1 | 1610 | neg(reg1) // neg reg1 |
7597 | akron1 | 1611 | // @@: |
1612 | |||
7693 | akron1 | 1613 | |IL.opCOPY: |
7597 | akron1 | 1614 | PushAll(2); |
1615 | pushc(param2); |
||
7693 | akron1 | 1616 | CallRTL(pic, IL._move2) |
7597 | akron1 | 1617 | |
7693 | akron1 | 1618 | |IL.opMOVE: |
7597 | akron1 | 1619 | PushAll(3); |
7693 | akron1 | 1620 | CallRTL(pic, IL._move2) |
7597 | akron1 | 1621 | |
7693 | akron1 | 1622 | |IL.opCOPYA: |
7597 | akron1 | 1623 | PushAll(4); |
1624 | pushc(param2); |
||
7693 | akron1 | 1625 | CallRTL(pic, IL._arrcpy); |
7597 | akron1 | 1626 | GetRegA |
1627 | |||
7693 | akron1 | 1628 | |IL.opCOPYS: |
7597 | akron1 | 1629 | PushAll(4); |
1630 | pushc(param2); |
||
7693 | akron1 | 1631 | CallRTL(pic, IL._strcpy) |
7597 | akron1 | 1632 | |
7693 | akron1 | 1633 | |IL.opROT: |
7597 | akron1 | 1634 | PushAll(0); |
1635 | push(esp); |
||
1636 | pushc(param2); |
||
7693 | akron1 | 1637 | CallRTL(pic, IL._rot) |
7597 | akron1 | 1638 | |
7693 | akron1 | 1639 | |IL.opNEW: |
7597 | akron1 | 1640 | PushAll(1); |
1641 | n := param2 + 8; |
||
7693 | akron1 | 1642 | ASSERT(UTILS.Align(n, 32)); |
7597 | akron1 | 1643 | pushc(n); |
1644 | pushc(param1); |
||
7693 | akron1 | 1645 | CallRTL(pic, IL._new) |
7597 | akron1 | 1646 | |
7693 | akron1 | 1647 | |IL.opDISP: |
7597 | akron1 | 1648 | PushAll(1); |
7693 | akron1 | 1649 | CallRTL(pic, IL._dispose) |
7597 | akron1 | 1650 | |
7693 | akron1 | 1651 | |IL.opEQS .. IL.opGES: |
7597 | akron1 | 1652 | PushAll(4); |
7693 | akron1 | 1653 | pushc(opcode - IL.opEQS); |
1654 | CallRTL(pic, IL._strcmp); |
||
7597 | akron1 | 1655 | GetRegA |
1656 | |||
7693 | akron1 | 1657 | |IL.opEQSW .. IL.opGESW: |
7597 | akron1 | 1658 | PushAll(4); |
7693 | akron1 | 1659 | pushc(opcode - IL.opEQSW); |
1660 | CallRTL(pic, IL._strcmpw); |
||
7597 | akron1 | 1661 | GetRegA |
1662 | |||
7693 | akron1 | 1663 | |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP: |
7597 | akron1 | 1664 | UnOp(reg1); |
7693 | akron1 | 1665 | CASE opcode OF |
1666 | |IL.opEQP, IL.opNEP: |
||
7597 | akron1 | 1667 | IF pic THEN |
7693 | akron1 | 1668 | reg2 := GetAnyReg(); |
7597 | akron1 | 1669 | Pic(reg2, BIN.PICCODE, param1); |
1670 | cmprr(reg1, reg2); |
||
1671 | drop |
||
1672 | ELSE |
||
1673 | OutByte2(081H, 0F8H + reg1); // cmp reg1, L |
||
1674 | Reloc(BIN.RCODE, param1) |
||
1675 | END |
||
1676 | |||
7693 | akron1 | 1677 | |IL.opEQIP, IL.opNEIP: |
7597 | akron1 | 1678 | IF pic THEN |
7693 | akron1 | 1679 | reg2 := GetAnyReg(); |
7597 | akron1 | 1680 | Pic(reg2, BIN.PICIMP, param1); |
1681 | OutByte2(03BH, reg1 * 8 + reg2); //cmp reg1, dword [reg2] |
||
1682 | drop |
||
1683 | ELSE |
||
1684 | OutByte2(3BH, 05H + reg1 * 8); // cmp reg1, dword[L] |
||
1685 | Reloc(BIN.RIMP, param1) |
||
1686 | END |
||
1687 | |||
1688 | END; |
||
1689 | drop; |
||
7693 | akron1 | 1690 | reg1 := GetAnyReg(); |
7597 | akron1 | 1691 | |
7693 | akron1 | 1692 | CASE opcode OF |
1693 | |IL.opEQP, IL.opEQIP: setcc(sete, reg1) |
||
1694 | |IL.opNEP, IL.opNEIP: setcc(setne, reg1) |
||
7597 | akron1 | 1695 | END; |
1696 | |||
1697 | andrc(reg1, 1) |
||
1698 | |||
7693 | akron1 | 1699 | |IL.opPUSHT: |
7597 | akron1 | 1700 | UnOp(reg1); |
7693 | akron1 | 1701 | reg2 := GetAnyReg(); |
7597 | akron1 | 1702 | OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH) // mov reg2, dword[reg1 - 4] |
1703 | |||
7693 | akron1 | 1704 | |IL.opISREC: |
7597 | akron1 | 1705 | PushAll(2); |
7693 | akron1 | 1706 | pushc(param2 * tcount); |
1707 | CallRTL(pic, IL._isrec); |
||
7597 | akron1 | 1708 | GetRegA |
1709 | |||
7693 | akron1 | 1710 | |IL.opIS: |
7597 | akron1 | 1711 | PushAll(1); |
7693 | akron1 | 1712 | pushc(param2 * tcount); |
1713 | CallRTL(pic, IL._is); |
||
7597 | akron1 | 1714 | GetRegA |
1715 | |||
7693 | akron1 | 1716 | |IL.opTYPEGR: |
7597 | akron1 | 1717 | PushAll(1); |
7693 | akron1 | 1718 | pushc(param2 * tcount); |
1719 | CallRTL(pic, IL._guardrec); |
||
7597 | akron1 | 1720 | GetRegA |
1721 | |||
7693 | akron1 | 1722 | |IL.opTYPEGP: |
7597 | akron1 | 1723 | UnOp(reg1); |
1724 | PushAll(0); |
||
1725 | push(reg1); |
||
7693 | akron1 | 1726 | pushc(param2 * tcount); |
1727 | CallRTL(pic, IL._guard); |
||
7597 | akron1 | 1728 | GetRegA |
1729 | |||
7693 | akron1 | 1730 | |IL.opTYPEGD: |
7597 | akron1 | 1731 | UnOp(reg1); |
1732 | PushAll(0); |
||
1733 | OutByte3(0FFH, 070H + reg1, 0FCH); // push dword[reg1 - 4] |
||
7693 | akron1 | 1734 | pushc(param2 * tcount); |
1735 | CallRTL(pic, IL._guardrec); |
||
7597 | akron1 | 1736 | GetRegA |
1737 | |||
7693 | akron1 | 1738 | |IL.opCASET: |
7597 | akron1 | 1739 | push(ecx); |
1740 | push(ecx); |
||
7693 | akron1 | 1741 | pushc(param2 * tcount); |
1742 | CallRTL(pic, IL._guardrec); |
||
7597 | akron1 | 1743 | pop(ecx); |
1744 | test(eax); |
||
1745 | jcc(jne, param1) |
||
1746 | |||
7693 | akron1 | 1747 | |IL.opPACK: |
7597 | akron1 | 1748 | BinOp(reg1, reg2); |
1749 | push(reg2); |
||
1750 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1751 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1752 | OutByte2(0D9H, 0FDH); // fscale |
||
1753 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1754 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
1755 | pop(reg2); |
||
1756 | drop; |
||
1757 | drop |
||
1758 | |||
7693 | akron1 | 1759 | |IL.opPACKC: |
7597 | akron1 | 1760 | UnOp(reg1); |
1761 | pushc(param2); |
||
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(reg1); |
||
1768 | drop |
||
1769 | |||
7693 | akron1 | 1770 | |IL.opUNPK: |
7597 | akron1 | 1771 | BinOp(reg1, reg2); |
1772 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1773 | OutByte2(0D9H, 0F4H); // fxtract |
||
1774 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1775 | OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] |
||
1776 | drop; |
||
1777 | drop |
||
1778 | |||
7693 | akron1 | 1779 | |IL.opPUSHF: |
7597 | akron1 | 1780 | subrc(esp, 8); |
1781 | OutByte3(0DDH, 01CH, 024H) // fstp qword[esp] |
||
1782 | |||
7693 | akron1 | 1783 | |IL.opLOADF: |
7597 | akron1 | 1784 | UnOp(reg1); |
1785 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1786 | drop |
||
1787 | |||
7693 | akron1 | 1788 | |IL.opCONSTF: |
7597 | akron1 | 1789 | float := cmd.float; |
1790 | IF float = 0.0 THEN |
||
1791 | OutByte2(0D9H, 0EEH) // fldz |
||
1792 | ELSIF float = 1.0 THEN |
||
1793 | OutByte2(0D9H, 0E8H) // fld1 |
||
1794 | ELSIF float = -1.0 THEN |
||
1795 | OutByte2(0D9H, 0E8H); // fld1 |
||
1796 | OutByte2(0D9H, 0E0H) // fchs |
||
1797 | ELSE |
||
1798 | n := UTILS.splitf(float, a, b); |
||
1799 | pushc(b); |
||
1800 | pushc(a); |
||
1801 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
1802 | addrc(esp, 8) |
||
1803 | END |
||
1804 | |||
7693 | akron1 | 1805 | |IL.opSAVEF: |
7597 | akron1 | 1806 | UnOp(reg1); |
1807 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1808 | drop |
||
1809 | |||
7693 | akron1 | 1810 | |IL.opADDF, IL.opADDFI: |
7597 | akron1 | 1811 | OutByte2(0DEH, 0C1H) // faddp st1, st |
1812 | |||
7693 | akron1 | 1813 | |IL.opSUBF: |
7597 | akron1 | 1814 | OutByte2(0DEH, 0E9H) // fsubp st1, st |
1815 | |||
7693 | akron1 | 1816 | |IL.opSUBFI: |
7597 | akron1 | 1817 | OutByte2(0DEH, 0E1H) // fsubrp st1, st |
1818 | |||
7693 | akron1 | 1819 | |IL.opMULF: |
7597 | akron1 | 1820 | OutByte2(0DEH, 0C9H) // fmulp st1, st |
1821 | |||
7693 | akron1 | 1822 | |IL.opDIVF: |
7597 | akron1 | 1823 | OutByte2(0DEH, 0F9H) // fdivp st1, st |
1824 | |||
7693 | akron1 | 1825 | |IL.opDIVFI: |
7597 | akron1 | 1826 | OutByte2(0DEH, 0F1H) // fdivrp st1, st |
1827 | |||
7693 | akron1 | 1828 | |IL.opUMINF: |
7597 | akron1 | 1829 | OutByte2(0D9H, 0E0H) // fchs |
1830 | |||
7693 | akron1 | 1831 | |IL.opFABS: |
7597 | akron1 | 1832 | OutByte2(0D9H, 0E1H) // fabs |
1833 | |||
7693 | akron1 | 1834 | |IL.opFLT: |
7597 | akron1 | 1835 | UnOp(reg1); |
1836 | push(reg1); |
||
1837 | OutByte3(0DBH, 004H, 024H); // fild dword[esp] |
||
1838 | pop(reg1); |
||
1839 | drop |
||
1840 | |||
7693 | akron1 | 1841 | |IL.opFLOOR: |
7597 | akron1 | 1842 | subrc(esp, 8); |
1843 | OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H); // fstcw word[esp+4] |
||
1844 | OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H); // fstcw word[esp+6] |
||
1845 | OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH); // and word[esp+4], 1111001111111111b |
||
1846 | OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H); // or word[esp+4], 0000010000000000b |
||
1847 | OutByte2(0D9H, 06CH); OutByte2(024H, 004H); // fldcw word[esp+4] |
||
1848 | OutByte2(0D9H, 0FCH); // frndint |
||
1849 | OutByte3(0DBH, 01CH, 024H); // fistp dword[esp] |
||
7693 | akron1 | 1850 | pop(GetAnyReg()); |
7597 | akron1 | 1851 | OutByte2(0D9H, 06CH); OutByte2(024H, 002H); // fldcw word[esp+2] |
1852 | addrc(esp, 4) |
||
1853 | |||
7693 | akron1 | 1854 | |IL.opEQF: |
7597 | akron1 | 1855 | GetRegA; |
1856 | OutByte2(0DAH, 0E9H); // fucompp |
||
1857 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1858 | OutByte(09EH); // sahf |
||
1859 | movrc(eax, 0); |
||
1860 | OutByte2(07AH, 003H); // jp L |
||
1861 | setcc(sete, al) |
||
1862 | // L: |
||
1863 | |||
7693 | akron1 | 1864 | |IL.opNEF: |
7597 | akron1 | 1865 | GetRegA; |
1866 | OutByte2(0DAH, 0E9H); // fucompp |
||
1867 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1868 | OutByte(09EH); // sahf |
||
1869 | movrc(eax, 0); |
||
1870 | OutByte2(07AH, 003H); // jp L |
||
1871 | setcc(setne, al) |
||
1872 | // L: |
||
1873 | |||
7693 | akron1 | 1874 | |IL.opLTF: |
7597 | akron1 | 1875 | GetRegA; |
1876 | OutByte2(0DAH, 0E9H); // fucompp |
||
1877 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1878 | OutByte(09EH); // sahf |
||
1879 | movrc(eax, 0); |
||
1880 | OutByte2(07AH, 00EH); // jp L |
||
1881 | setcc(setc, al); |
||
1882 | setcc(sete, ah); |
||
1883 | test(eax); |
||
1884 | setcc(sete, al); |
||
1885 | andrc(eax, 1) |
||
1886 | // L: |
||
1887 | |||
7693 | akron1 | 1888 | |IL.opGTF: |
7597 | akron1 | 1889 | GetRegA; |
1890 | OutByte2(0DAH, 0E9H); // fucompp |
||
1891 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1892 | OutByte(09EH); // sahf |
||
1893 | movrc(eax, 0); |
||
1894 | OutByte2(07AH, 00FH); // jp L |
||
1895 | setcc(setc, al); |
||
1896 | setcc(sete, ah); |
||
1897 | cmprc(eax, 1); |
||
1898 | setcc(sete, al); |
||
1899 | andrc(eax, 1) |
||
1900 | // L: |
||
1901 | |||
7693 | akron1 | 1902 | |IL.opLEF: |
7597 | akron1 | 1903 | GetRegA; |
1904 | OutByte2(0DAH, 0E9H); // fucompp |
||
1905 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1906 | OutByte(09EH); // sahf |
||
1907 | movrc(eax, 0); |
||
1908 | OutByte2(07AH, 003H); // jp L |
||
1909 | setcc(setnc, al) |
||
1910 | // L: |
||
1911 | |||
7693 | akron1 | 1912 | |IL.opGEF: |
7597 | akron1 | 1913 | GetRegA; |
1914 | OutByte2(0DAH, 0E9H); // fucompp |
||
1915 | OutByte3(09BH, 0DFH, 0E0H); // fstsw ax |
||
1916 | OutByte(09EH); // sahf |
||
1917 | movrc(eax, 0); |
||
1918 | OutByte2(07AH, 010H); // jp L |
||
1919 | setcc(setc, al); |
||
1920 | setcc(sete, ah); |
||
1921 | OutByte2(000H, 0E0H); // add al,ah |
||
1922 | OutByte2(03CH, 001H); // cmp al,1 |
||
1923 | setcc(sete, al); |
||
1924 | andrc(eax, 1) |
||
1925 | // L: |
||
1926 | |||
7693 | akron1 | 1927 | |IL.opINF: |
7597 | akron1 | 1928 | pushc(7FF00000H); |
1929 | pushc(0); |
||
1930 | OutByte3(0DDH, 004H, 024H); // fld qword[esp] |
||
1931 | addrc(esp, 8) |
||
1932 | |||
7693 | akron1 | 1933 | |IL.opLADR_UNPK: |
7597 | akron1 | 1934 | n := param2 * 4; |
7693 | akron1 | 1935 | reg1 := GetAnyReg(); |
7597 | akron1 | 1936 | OutByte2(8DH, 45H + reg1 * 8 + long(n)); // lea reg1, dword[ebp + n] |
1937 | OutIntByte(n); |
||
1938 | BinOp(reg1, reg2); |
||
1939 | OutByte2(0DDH, reg1); // fld qword[reg1] |
||
1940 | OutByte2(0D9H, 0F4H); // fxtract |
||
1941 | OutByte2(0DDH, 018H + reg1); // fstp qword[reg1] |
||
1942 | OutByte2(0DBH, 018H + reg2); // fistp dword[reg2] |
||
1943 | drop; |
||
1944 | drop |
||
1945 | |||
7693 | akron1 | 1946 | |IL.opSADR_PARAM: |
7597 | akron1 | 1947 | IF pic THEN |
7693 | akron1 | 1948 | reg1 := GetAnyReg(); |
7597 | akron1 | 1949 | Pic(reg1, BIN.PICDATA, stroffs + param2); |
1950 | push(reg1); |
||
1951 | drop |
||
1952 | ELSE |
||
1953 | OutByte(068H); // push _data + stroffs + param2 |
||
1954 | Reloc(BIN.RDATA, stroffs + param2) |
||
1955 | END |
||
1956 | |||
7693 | akron1 | 1957 | |IL.opVADR_PARAM: |
7597 | akron1 | 1958 | n := param2 * 4; |
1959 | OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] |
||
1960 | OutIntByte(n) |
||
1961 | |||
7693 | akron1 | 1962 | |IL.opCONST_PARAM: |
7597 | akron1 | 1963 | pushc(param2) |
1964 | |||
7693 | akron1 | 1965 | |IL.opGLOAD32_PARAM: |
7597 | akron1 | 1966 | IF pic THEN |
7693 | akron1 | 1967 | reg1 := GetAnyReg(); |
7597 | akron1 | 1968 | Pic(reg1, BIN.PICBSS, param2); |
1969 | OutByte2(0FFH, 30H + reg1); // push dword[reg1] |
||
1970 | drop |
||
1971 | ELSE |
||
1972 | OutByte2(0FFH, 035H); // push dword[_bss + param2] |
||
1973 | Reloc(BIN.RBSS, param2) |
||
1974 | END |
||
1975 | |||
7693 | akron1 | 1976 | |IL.opLLOAD32_PARAM: |
7597 | akron1 | 1977 | n := param2 * 4; |
1978 | OutByte2(0FFH, 75H + long(n)); // push dword[ebp + n] |
||
1979 | OutIntByte(n) |
||
1980 | |||
7693 | akron1 | 1981 | |IL.opLOAD32_PARAM: |
7597 | akron1 | 1982 | UnOp(reg1); |
1983 | OutByte2(0FFH, 30H + reg1); // push dword[reg1] |
||
1984 | drop |
||
1985 | |||
7693 | akron1 | 1986 | |IL.opGADR_SAVEC: |
7597 | akron1 | 1987 | IF pic THEN |
7693 | akron1 | 1988 | reg1 := GetAnyReg(); |
7597 | akron1 | 1989 | Pic(reg1, BIN.PICBSS, param1); |
1990 | OutByte2(0C7H, reg1); // mov dword[reg1], param2 |
||
1991 | OutInt(param2); |
||
1992 | drop |
||
1993 | ELSE |
||
7693 | akron1 | 1994 | OutByte2(0C7H, 05H); // mov dword[_bss + param1], param2 |
7597 | akron1 | 1995 | Reloc(BIN.RBSS, param1); |
1996 | OutInt(param2) |
||
1997 | END |
||
1998 | |||
7693 | akron1 | 1999 | |IL.opLADR_SAVEC: |
7597 | akron1 | 2000 | n := param1 * 4; |
2001 | OutByte2(0C7H, 45H + long(n)); // mov dword[ebp + n], param2 |
||
2002 | OutIntByte(n); |
||
2003 | OutInt(param2) |
||
2004 | |||
7693 | akron1 | 2005 | |IL.opLADR_SAVE: |
7597 | akron1 | 2006 | n := param2 * 4; |
2007 | UnOp(reg1); |
||
2008 | OutByte2(89H, 45H + reg1 * 8 + long(n)); // mov dword[ebp + n], reg1 |
||
2009 | OutIntByte(n); |
||
2010 | drop |
||
2011 | |||
7693 | akron1 | 2012 | |IL.opLADR_INCC: |
7597 | akron1 | 2013 | n := param1 * 4; |
7693 | akron1 | 2014 | IF ABS(param2) = 1 THEN |
2015 | OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); // inc/dec dword[ebp + n] |
||
2016 | OutIntByte(n) |
||
2017 | ELSE |
||
2018 | OutByte2(81H + short(param2), 45H + long(n)); // add dword[ebp + n], param2 |
||
2019 | OutIntByte(n); |
||
2020 | OutIntByte(param2) |
||
2021 | END |
||
7597 | akron1 | 2022 | |
7693 | akron1 | 2023 | |IL.opLADR_INCCB, IL.opLADR_DECCB: |
7597 | akron1 | 2024 | n := param1 * 4; |
7693 | akron1 | 2025 | IF param2 = 1 THEN |
2026 | OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n)); // inc/dec byte[ebp + n] |
||
2027 | OutIntByte(n) |
||
2028 | ELSE |
||
2029 | OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); // add/sub byte[ebp + n], param2 |
||
2030 | OutIntByte(n); |
||
2031 | OutByte(param2 MOD 256) |
||
2032 | END |
||
7597 | akron1 | 2033 | |
7693 | akron1 | 2034 | |IL.opLADR_INC, IL.opLADR_DEC: |
7597 | akron1 | 2035 | n := param2 * 4; |
2036 | UnOp(reg1); |
||
7693 | akron1 | 2037 | OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); // add/sub dword[ebp + n], reg1 |
7597 | akron1 | 2038 | OutIntByte(n); |
2039 | drop |
||
2040 | |||
7693 | akron1 | 2041 | |IL.opLADR_INCB, IL.opLADR_DECB: |
7597 | akron1 | 2042 | n := param2 * 4; |
2043 | UnOp(reg1); |
||
7693 | akron1 | 2044 | OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); // add/sub byte[ebp + n], reg1 |
7597 | akron1 | 2045 | OutIntByte(n); |
2046 | drop |
||
2047 | |||
7693 | akron1 | 2048 | |IL.opLADR_INCL, IL.opLADR_EXCL: |
7597 | akron1 | 2049 | n := param2 * 4; |
2050 | UnOp(reg1); |
||
2051 | cmprc(reg1, 32); |
||
2052 | label := NewLabel(); |
||
2053 | jcc(jnb, label); |
||
7693 | akron1 | 2054 | OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1 |
7597 | akron1 | 2055 | OutIntByte(n); |
2056 | SetLabel(label); |
||
2057 | drop |
||
2058 | |||
7693 | akron1 | 2059 | |IL.opLADR_INCLC, IL.opLADR_EXCLC: |
7597 | akron1 | 2060 | n := param1 * 4; |
7693 | akron1 | 2061 | OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2 |
7597 | akron1 | 2062 | OutIntByte(n); |
2063 | OutByte(param2) |
||
2064 | |||
7693 | akron1 | 2065 | |IL.opLOOP, IL.opENDLOOP: |
7597 | akron1 | 2066 | |
6613 | leency | 2067 | END; |
7597 | akron1 | 2068 | |
2069 | cmd := cmd.next(COMMAND) |
||
6613 | leency | 2070 | END; |
2071 | |||
7597 | akron1 | 2072 | ASSERT(R.pushed = 0); |
2073 | ASSERT(R.top = -1) |
||
6613 | leency | 2074 | |
7597 | akron1 | 2075 | END translate; |
6613 | leency | 2076 | |
2077 | |||
7693 | akron1 | 2078 | PROCEDURE prolog (code: IL.CODES; pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER); |
7597 | akron1 | 2079 | VAR |
7693 | akron1 | 2080 | reg1, entry, dcount: INTEGER; |
6613 | leency | 2081 | |
7597 | akron1 | 2082 | BEGIN |
6613 | leency | 2083 | |
7597 | akron1 | 2084 | entry := NewLabel(); |
2085 | SetLabel(entry); |
||
6613 | leency | 2086 | |
7597 | akron1 | 2087 | IF target = mConst.Target_iDLL THEN |
2088 | push(ebp); |
||
2089 | mov(ebp, esp); |
||
2090 | OutByte3(0FFH, 75H, 16); // push dword[ebp+16] |
||
2091 | OutByte3(0FFH, 75H, 12); // push dword[ebp+12] |
||
2092 | OutByte3(0FFH, 75H, 8); // push dword[ebp+8] |
||
7693 | akron1 | 2093 | CallRTL(pic, IL._dllentry); |
7597 | akron1 | 2094 | test(eax); |
2095 | jcc(je, dllret) |
||
2096 | ELSIF target = mConst.Target_iObject THEN |
||
2097 | SetLabel(dllinit) |
||
2098 | END; |
||
6613 | leency | 2099 | |
7597 | akron1 | 2100 | IF target = mConst.Target_iKolibri THEN |
7693 | akron1 | 2101 | reg1 := GetAnyReg(); |
7597 | akron1 | 2102 | Pic(reg1, BIN.IMPTAB, 0); |
2103 | push(reg1); // push IMPORT |
||
2104 | drop |
||
2105 | ELSIF target = mConst.Target_iObject THEN |
||
2106 | OutByte(68H); // push IMPORT |
||
2107 | Reloc(BIN.IMPTAB, 0) |
||
2108 | ELSIF target = mConst.Target_iELF32 THEN |
||
2109 | push(esp) |
||
2110 | ELSE |
||
2111 | pushc(0) |
||
7667 | akron1 | 2112 | END; |
2113 | |||
7597 | akron1 | 2114 | IF pic THEN |
7693 | akron1 | 2115 | reg1 := GetAnyReg(); |
7597 | akron1 | 2116 | Pic(reg1, BIN.PICCODE, entry); |
2117 | push(reg1); // push CODE |
||
2118 | drop |
||
2119 | ELSE |
||
2120 | OutByte(68H); // push CODE |
||
2121 | Reloc(BIN.RCODE, entry) |
||
2122 | END; |
||
6613 | leency | 2123 | |
7597 | akron1 | 2124 | IF pic THEN |
7693 | akron1 | 2125 | reg1 := GetAnyReg(); |
7597 | akron1 | 2126 | Pic(reg1, BIN.PICDATA, 0); |
2127 | push(reg1); // push _data |
||
2128 | drop |
||
2129 | ELSE |
||
2130 | OutByte(68H); // push _data |
||
2131 | Reloc(BIN.RDATA, 0) |
||
2132 | END; |
||
6613 | leency | 2133 | |
7597 | akron1 | 2134 | dcount := CHL.Length(code.data); |
6613 | leency | 2135 | |
7597 | akron1 | 2136 | pushc(tcount); |
6613 | leency | 2137 | |
7597 | akron1 | 2138 | IF pic THEN |
7693 | akron1 | 2139 | reg1 := GetAnyReg(); |
7597 | akron1 | 2140 | Pic(reg1, BIN.PICDATA, tcount * 4 + dcount); |
2141 | push(reg1); // push _data + tcount * 4 + dcount |
||
2142 | drop |
||
2143 | ELSE |
||
2144 | OutByte(68H); // push _data |
||
2145 | Reloc(BIN.RDATA, tcount * 4 + dcount) |
||
2146 | END; |
||
6613 | leency | 2147 | |
7693 | akron1 | 2148 | CallRTL(pic, IL._init) |
7597 | akron1 | 2149 | END prolog; |
6613 | leency | 2150 | |
2151 | |||
7693 | akron1 | 2152 | PROCEDURE epilog (code: IL.CODES; pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER); |
7597 | akron1 | 2153 | VAR |
7693 | akron1 | 2154 | exp: IL.EXPORT_PROC; |
7597 | akron1 | 2155 | path, name, ext: PATHS.PATH; |
6613 | leency | 2156 | |
7693 | akron1 | 2157 | dcount, i: INTEGER; |
6613 | leency | 2158 | |
7597 | akron1 | 2159 | |
2160 | PROCEDURE import (imp: LISTS.LIST); |
||
2161 | VAR |
||
7693 | akron1 | 2162 | lib: IL.IMPORT_LIB; |
2163 | proc: IL.IMPORT_PROC; |
||
7597 | akron1 | 2164 | |
2165 | BEGIN |
||
2166 | |||
7693 | akron1 | 2167 | lib := imp.first(IL.IMPORT_LIB); |
7597 | akron1 | 2168 | WHILE lib # NIL DO |
2169 | BIN.Import(program, lib.name, 0); |
||
7693 | akron1 | 2170 | proc := lib.procs.first(IL.IMPORT_PROC); |
7597 | akron1 | 2171 | WHILE proc # NIL DO |
2172 | BIN.Import(program, proc.name, proc.label); |
||
7693 | akron1 | 2173 | proc := proc.next(IL.IMPORT_PROC) |
7597 | akron1 | 2174 | END; |
7693 | akron1 | 2175 | lib := lib.next(IL.IMPORT_LIB) |
7597 | akron1 | 2176 | END |
2177 | |||
2178 | END import; |
||
2179 | |||
2180 | |||
6613 | leency | 2181 | BEGIN |
2182 | |||
7597 | akron1 | 2183 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN |
2184 | pushc(0); |
||
7693 | akron1 | 2185 | CallRTL(pic, IL._exit); |
7597 | akron1 | 2186 | ELSIF target = mConst.Target_iDLL THEN |
2187 | SetLabel(dllret); |
||
2188 | movrc(eax, 1); |
||
2189 | OutByte(0C9H); // leave |
||
2190 | OutByte3(0C2H, 0CH, 0) // ret 12 |
||
2191 | ELSIF target = mConst.Target_iObject THEN |
||
2192 | movrc(eax, 1); |
||
2193 | OutByte(0C3H) // ret |
||
7693 | akron1 | 2194 | ELSIF target = mConst.Target_iELFSO32 THEN |
2195 | OutByte(0C3H); // ret |
||
2196 | SetLabel(sofinit); |
||
2197 | CallRTL(pic, IL._sofinit); |
||
2198 | OutByte(0C3H) // ret |
||
7597 | akron1 | 2199 | END; |
6613 | leency | 2200 | |
7597 | akron1 | 2201 | fixup; |
2202 | |||
2203 | dcount := CHL.Length(code.data); |
||
2204 | |||
2205 | FOR i := 0 TO tcount - 1 DO |
||
2206 | BIN.PutData32LE(program, CHL.GetInt(code.types, i)) |
||
6613 | leency | 2207 | END; |
2208 | |||
7597 | akron1 | 2209 | FOR i := 0 TO dcount - 1 DO |
2210 | BIN.PutData(program, CHL.GetByte(code.data, i)) |
||
6613 | leency | 2211 | END; |
2212 | |||
7597 | akron1 | 2213 | program.modname := CHL.Length(program.data); |
6613 | leency | 2214 | |
7597 | akron1 | 2215 | PATHS.split(modname, path, name, ext); |
2216 | BIN.PutDataStr(program, name); |
||
2217 | BIN.PutDataStr(program, ext); |
||
2218 | BIN.PutData(program, 0); |
||
6613 | leency | 2219 | |
7597 | akron1 | 2220 | IF target = mConst.Target_iObject THEN |
2221 | BIN.Export(program, "lib_init", dllinit); |
||
2222 | END; |
||
6613 | leency | 2223 | |
7693 | akron1 | 2224 | exp := code.export.first(IL.EXPORT_PROC); |
7597 | akron1 | 2225 | WHILE exp # NIL DO |
2226 | BIN.Export(program, exp.name, exp.label); |
||
7693 | akron1 | 2227 | exp := exp.next(IL.EXPORT_PROC) |
6613 | leency | 2228 | END; |
2229 | |||
7597 | akron1 | 2230 | import(code.import); |
6613 | leency | 2231 | |
7693 | akron1 | 2232 | code.bss := MAX(code.bss, MAX(code.dmin - CHL.Length(code.data), 4)); |
6613 | leency | 2233 | |
7693 | akron1 | 2234 | BIN.SetParams(program, code.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536)); |
7597 | akron1 | 2235 | |
2236 | END epilog; |
||
2237 | |||
2238 | |||
7693 | akron1 | 2239 | PROCEDURE CodeGen* (code: IL.CODES; outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); |
7597 | akron1 | 2240 | VAR |
7693 | akron1 | 2241 | dllret, dllinit, sofinit: INTEGER; |
2242 | opt: PROG.OPTIONS; |
||
7597 | akron1 | 2243 | |
6613 | leency | 2244 | BEGIN |
7693 | akron1 | 2245 | tcount := CHL.Length(code.types); |
6613 | leency | 2246 | |
7693 | akron1 | 2247 | opt := options; |
7597 | akron1 | 2248 | CodeList := LISTS.create(NIL); |
2249 | |||
2250 | program := BIN.create(code.lcount); |
||
2251 | |||
2252 | dllinit := NewLabel(); |
||
2253 | dllret := NewLabel(); |
||
7693 | akron1 | 2254 | sofinit := NewLabel(); |
7597 | akron1 | 2255 | |
2256 | IF target = mConst.Target_iObject THEN |
||
7693 | akron1 | 2257 | opt.pic := FALSE |
6613 | leency | 2258 | END; |
7597 | akron1 | 2259 | |
7693 | akron1 | 2260 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32, mConst.Target_iELFSO32} THEN |
2261 | opt.pic := TRUE |
||
7597 | akron1 | 2262 | END; |
2263 | |||
7693 | akron1 | 2264 | REG.Init(R, push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); |
7597 | akron1 | 2265 | |
7693 | akron1 | 2266 | prolog(code, opt.pic, target, opt.stack, dllinit, dllret); |
2267 | translate(code, opt.pic, tcount * 4); |
||
2268 | epilog(code, opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit); |
||
7597 | akron1 | 2269 | |
2270 | BIN.fixup(program); |
||
2271 | |||
2272 | IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN |
||
7693 | akron1 | 2273 | PE32.write(program, outname, opt.base, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE) |
7597 | akron1 | 2274 | ELSIF target = mConst.Target_iKolibri THEN |
2275 | KOS.write(program, outname) |
||
2276 | ELSIF target = mConst.Target_iObject THEN |
||
7693 | akron1 | 2277 | MSCOFF.write(program, outname, opt.version) |
2278 | ELSIF target IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN |
||
2279 | ELF.write(program, outname, sofinit, target = mConst.Target_iELFSO32, FALSE) |
||
6613 | leency | 2280 | END |
2281 | |||
7597 | akron1 | 2282 | END CodeGen; |
7209 | akron1 | 2283 | |
7597 | akron1 | 2284 | |
2285 | PROCEDURE SetProgram* (prog: BIN.PROGRAM); |
||
7209 | akron1 | 2286 | BEGIN |
7597 | akron1 | 2287 | program := prog; |
2288 | CodeList := LISTS.create(NIL) |
||
2289 | END SetProgram; |
||
2290 | |||
2291 | |||
6613 | leency | 2292 | END X86.>>>>=>=>>>=>>=>=>=>=>> |