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