From 0ea0ebcf81afc722f731b22a1e1d5d7819830efd Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 18 Nov 2019 00:24:24 -0800 Subject: 5751 - start of table of Mu primitives So far this is just the same as our most recent tests. But now we have a 'DSL' for adding more primitives. --- html/apps/mu.subx.html | 2039 ++++++++++++++++++++++++++---------------------- 1 file changed, 1099 insertions(+), 940 deletions(-) (limited to 'html') diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index c33a1111..a18bf17d 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -16,6 +16,7 @@ a { color:inherit; } * { font-size:12pt; font-size: 1em; } .subxComment { color: #005faf; } .subxFunction { color: #af5f00; text-decoration: underline; } +.subxMinorFunction { color: #875f5f; } .LineNr { } .subxS1Comment { color: #0000af; } .CommentedCode { color: #8a8a8a; } @@ -911,9 +912,9 @@ if ('onhashchange' in window) { 870 # 871 (write-buffered %edi *ecx) 872 (write-buffered %edi ":\n") - 873 (emit-subx-prologue %edi) + 873 (emit-subx-prologue %edi) 874 (emit-subx-block %edi *(ecx+0x10)) # Function-body - 875 (emit-subx-epilogue %edi) + 875 (emit-subx-epilogue %edi) 876 $emit-subx-function:end: 877 # . restore registers 878 5f/pop-to-edi @@ -945,19 +946,19 @@ if ('onhashchange' in window) { 904 # if stmt matches a primitive, emit it 905 { 906 $emit-subx-statement:primitive: - 907 (find-matching-primitive *(ebp+0x14) *(ebp+0xc)) # primitives, stmt => curr/eax + 907 (find-matching-primitive *(ebp+0x14) *(ebp+0xc)) # primitives, stmt => curr/eax 908 3d/compare-eax-and 0/imm32 909 74/jump-if-equal break/disp8 - 910 (emit-subx-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax) # out, stmt, vars, curr + 910 (emit-subx-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax) # out, stmt, vars, curr 911 e9/jump $emit-subx-statement:end/disp32 912 } 913 # else if stmt matches a function, emit a call to it 914 { 915 $emit-subx-statement:call: - 916 (find-matching-function *(ebp+0x18) *(ebp+0xc)) # functions, stmt => curr/eax + 916 (find-matching-function *(ebp+0x18) *(ebp+0xc)) # functions, stmt => curr/eax 917 3d/compare-eax-and 0/imm32 918 74/jump-if-equal break/disp8 - 919 (emit-subx-call *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax) # out, stmt, vars, curr + 919 (emit-subx-call *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax) # out, stmt, vars, curr 920 e9/jump $emit-subx-statement:end/disp32 921 } 922 # else abort @@ -983,506 +984,506 @@ if ('onhashchange' in window) { 942 cd/syscall 0x80/imm8 943 # never gets here 944 - 945 emit-subx-primitive: # out : (address buffered-file), stmt : (address statement), vars : (address variable), primitive : (address function) - 946 # . prologue - 947 55/push-ebp - 948 89/<- %ebp 4/r32/esp - 949 # . save registers - 950 50/push-eax - 951 51/push-ecx - 952 # ecx = primitive - 953 8b/-> *(ebp+0x14) 1/r32/ecx - 954 # emit primitive name - 955 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name - 956 # emit rm32 if necessary - 957 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt - 958 #? # emit r32 if necessary - 959 #? (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt - 960 #? # emit imm32 if necessary - 961 #? (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt - 962 $emit-subx-primitive:end: - 963 # . restore registers - 964 59/pop-to-ecx - 965 58/pop-to-eax - 966 # . epilogue - 967 89/<- %esp 5/r32/ebp - 968 5d/pop-to-ebp - 969 c3/return - 970 - 971 emit-subx-rm32: # out : (address buffered-file), l : arg-location, stmt : (address statement) - 972 # . prologue - 973 55/push-ebp - 974 89/<- %ebp 4/r32/esp - 975 # . save registers - 976 50/push-eax - 977 # if (l == 0) return - 978 81 7/subop/compare *(ebp+0xc) 0/imm32 - 979 74/jump-if-equal $emit-subx-rm32:end/disp8 - 980 # - 981 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax - 982 (emit-subx-call-operand *(ebp+8) %eax) # out, var - 983 $emit-subx-rm32:end: - 984 # . restore registers - 985 58/pop-to-eax - 986 # . epilogue - 987 89/<- %esp 5/r32/ebp - 988 5d/pop-to-ebp - 989 c3/return - 990 - 991 get-stmt-operand-from-arg-location: # stmt : (address statement), l : arg-location -> var/eax : (address variable) + 945 # Primitives supported + 946 == data + 947 Primitives: + 948 # increment var => ff 0/subop/increment *(ebp+__) + 949 "increment"/imm32/name + 950 Single-int-var-on-stack/imm32/inouts + 951 0/imm32/no-outputs + 952 "ff 0/subop/increment"/imm32/subx-name + 953 1/imm32/rm32-is-first-inout + 954 0/imm32/no-r32 + 955 0/imm32/no-imm32 + 956 _Primitive-inc-reg/imm32 + 957 _Primitive-inc-reg: + 958 # var/reg <- increment => ff 0/subop/increment %__ + 959 "increment"/imm32/name + 960 0/imm32/no-inouts + 961 Single-var-in-some-register/imm32/outputs + 962 "ff 0/subop/increment"/imm32/subx-name + 963 3/imm32/rm32-is-first-output + 964 0/imm32/no-r32 + 965 0/imm32/no-imm32 + 966 0/imm32/next + 967 + 968 Single-int-var-on-stack: + 969 Int-var-on-stack/imm32 + 970 0/imm32/next + 971 + 972 Int-var-on-stack: + 973 "arg1"/imm32/name + 974 1/imm32/type-int + 975 1/imm32/some-block-depth + 976 1/imm32/some-stack-offset + 977 0/imm32/no-register + 978 + 979 Single-var-in-some-register: + 980 Int-var-in-some-register/imm32 + 981 0/imm32/next + 982 + 983 Int-var-in-some-register: + 984 "arg1"/imm32/name + 985 1/imm32/type-int + 986 1/imm32/some-block-depth + 987 0/imm32/some-stack-offset + 988 "*"/imm32/register + 989 + 990 == code + 991 emit-subx-primitive: # out : (address buffered-file), stmt : (address statement), vars : (address variable), primitive : (address function) 992 # . prologue 993 55/push-ebp 994 89/<- %ebp 4/r32/esp 995 # . save registers - 996 51/push-ecx - 997 # eax = l - 998 8b/-> *(ebp+0xc) 0/r32/eax - 999 # ecx = stmt -1000 8b/-> *(ebp+8) 1/r32/ecx -1001 # if (l == 1) return stmt->inouts->var -1002 { -1003 3d/compare-eax-and 1/imm32 -1004 75/jump-if-not-equal break/disp8 -1005 $get-stmt-operand-from-arg-location:1: -1006 8b/-> *(ecx+4) 0/r32/eax # Stmt-inouts -1007 8b/-> *eax 0/r32/eax # Operand-var -1008 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -1009 } -1010 # if (l == 2) return stmt->inouts->next->var -1011 { -1012 3d/compare-eax-and 2/imm32 -1013 75/jump-if-not-equal break/disp8 -1014 $get-stmt-operand-from-arg-location:2: -1015 8b/-> *(ecx+4) 0/r32/eax # Stmt-inouts -1016 8b/-> *(eax+4) 0/r32/eax # Operand-next -1017 8b/-> *eax 0/r32/eax # Operand-var -1018 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -1019 } -1020 # if (l == 3) return stmt->outputs -1021 { -1022 3d/compare-eax-and 3/imm32 -1023 75/jump-if-not-equal break/disp8 -1024 $get-stmt-operand-from-arg-location:3: -1025 8b/-> *(ecx+8) 0/r32/eax # Stmt-outputs -1026 8b/-> *eax 0/r32/eax # Operand-var -1027 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -1028 } -1029 # abort -1030 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -1031 $get-stmt-operand-from-arg-location:end: -1032 # . restore registers -1033 59/pop-to-ecx -1034 # . epilogue -1035 89/<- %esp 5/r32/ebp -1036 5d/pop-to-ebp -1037 c3/return -1038 -1039 $get-stmt-operand-from-arg-location:abort: -1040 # error("invalid arg-location " eax) -1041 (write-buffered Stderr "invalid arg-location ") -1042 (print-int32-buffered Stderr %eax) -1043 (write-buffered Stderr "\n") -1044 (flush Stderr) -1045 # . syscall(exit, 1) -1046 bb/copy-to-ebx 1/imm32 -1047 b8/copy-to-eax 1/imm32/exit -1048 cd/syscall 0x80/imm8 -1049 # never gets here -1050 -1051 emit-subx-r32: # out : (address buffered-file), l : arg-location, stmt : (address statement) -1052 # . prologue -1053 55/push-ebp -1054 89/<- %ebp 4/r32/esp -1055 # . save registers -1056 50/push-eax -1057 51/push-ecx -1058 # location/ecx : enum = primitive->subx-r32 -1059 # if (location == 0) return -1060 # var/ecx : var = get-operand(stmt, primitive->subx-rm32) -1061 # emit-subx-call-operand(out, var) -1062 $emit-subx-r32:end: -1063 # . restore registers -1064 59/pop-to-ecx -1065 58/pop-to-eax -1066 # . epilogue -1067 89/<- %esp 5/r32/ebp -1068 5d/pop-to-ebp -1069 c3/return -1070 -1071 emit-subx-imm32: # out : (address buffered-file), l : arg-location, stmt : (address statement) -1072 # . prologue -1073 55/push-ebp -1074 89/<- %ebp 4/r32/esp -1075 # . save registers -1076 50/push-eax -1077 51/push-ecx -1078 # var/ecx : var = get-operand(stmt, primitive->subx-rm32) -1079 # emit-subx-call-operand(out, var) -1080 $emit-subx-imm32:end: -1081 # . restore registers -1082 59/pop-to-ecx -1083 58/pop-to-eax -1084 # . epilogue -1085 89/<- %esp 5/r32/ebp -1086 5d/pop-to-ebp -1087 c3/return -1088 -1089 emit-subx-call: # out : (address buffered-file), stmt : (address statement), vars : (address variable), callee : (address function) -1090 # . prologue -1091 55/push-ebp -1092 89/<- %ebp 4/r32/esp -1093 # . save registers -1094 50/push-eax -1095 51/push-ecx -1096 # -1097 (write-buffered *(ebp+8) "(") -1098 # - emit function name -1099 8b/-> *(ebp+0x14) 1/r32/ecx -1100 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -1101 # - emit arguments -1102 # var curr/ecx : (list var) = stmt->inouts -1103 8b/-> *(ebp+0xc) 1/r32/ecx -1104 8b/-> *(ecx+4) 1/r32/ecx # Stmt-inouts -1105 { -1106 # if (curr == null) break -1107 81 7/subop/compare %ecx 0/imm32 -1108 74/jump-if-equal break/disp8 -1109 # -1110 (emit-subx-call-operand *(ebp+8) *ecx) -1111 # curr = curr->next -1112 8b/-> *(ecx+4) 1/r32/ecx -1113 } -1114 # -1115 (write-buffered *(ebp+8) ")") -1116 $emit-subx-call:end: -1117 # . restore registers -1118 59/pop-to-ecx -1119 58/pop-to-eax -1120 # . epilogue -1121 89/<- %esp 5/r32/ebp -1122 5d/pop-to-ebp -1123 c3/return -1124 -1125 emit-subx-call-operand: # out : (address buffered-file), operand : (address variable) -1126 # . prologue -1127 55/push-ebp -1128 89/<- %ebp 4/r32/esp -1129 # . save registers -1130 50/push-eax -1131 # eax = operand -1132 8b/-> *(ebp+0xc) 0/r32/eax -1133 # if (operand->register) emit "%__" -1134 { -1135 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -1136 74/jump-if-equal break/disp8 -1137 $emit-subx-call-operand:register: -1138 (write-buffered *(ebp+8) " %") -1139 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register -1140 } -1141 # else if (operand->stack-offset) emit "*(ebp+__)" -1142 { -1143 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset -1144 74/jump-if-equal break/disp8 -1145 $emit-subx-call-operand:stack: -1146 (write-buffered *(ebp+8) Space) -1147 (write-buffered *(ebp+8) "*(ebp+") -1148 8b/-> *(ebp+0xc) 0/r32/eax -1149 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset -1150 (write-buffered *(ebp+8) ")") -1151 } -1152 $emit-subx-call-operand:end: -1153 # . restore registers -1154 58/pop-to-eax -1155 # . epilogue -1156 89/<- %esp 5/r32/ebp -1157 5d/pop-to-ebp -1158 c3/return -1159 -1160 find-matching-function: # functions : (address function), stmt : (address statement) -> result/eax : (address function) -1161 # . prologue -1162 55/push-ebp -1163 89/<- %ebp 4/r32/esp -1164 # . save registers -1165 51/push-ecx -1166 # var curr/ecx : (address function) = functions -1167 8b/-> *(ebp+8) 1/r32/ecx -1168 { -1169 # if (curr == null) break -1170 81 7/subop/compare %ecx 0/imm32 -1171 74/jump-if-equal break/disp8 -1172 # if match(curr, stmt) return curr -1173 { -1174 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -1175 3d/compare-eax-and 0/imm32 -1176 74/jump-if-equal break/disp8 -1177 89/<- %eax 1/r32/ecx -1178 eb/jump $find-matching-function:end/disp8 -1179 } -1180 # curr = curr->next -1181 8b/-> *(ecx+0x10) 1/r32/ecx # Function-next -1182 eb/jump loop/disp8 -1183 } -1184 # return null -1185 b8/copy-to-eax 0/imm32 -1186 $find-matching-function:end: -1187 # . restore registers -1188 59/pop-to-ecx -1189 # . epilogue -1190 89/<- %esp 5/r32/ebp -1191 5d/pop-to-ebp -1192 c3/return -1193 -1194 find-matching-primitive: # primitives : (address primitive), stmt : (address statement) -> result/eax : (address primitive) -1195 # . prologue -1196 55/push-ebp -1197 89/<- %ebp 4/r32/esp -1198 # . save registers -1199 51/push-ecx -1200 # var curr/ecx : (address primitive) = primitives -1201 8b/-> *(ebp+8) 1/r32/ecx -1202 { -1203 $find-matching-primitive:loop: -1204 # if (curr == null) break -1205 81 7/subop/compare %ecx 0/imm32 -1206 74/jump-if-equal break/disp8 -1207 # if match(curr, stmt) return curr -1208 { -1209 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -1210 3d/compare-eax-and 0/imm32 -1211 74/jump-if-equal break/disp8 -1212 89/<- %eax 1/r32/ecx -1213 eb/jump $find-matching-function:end/disp8 -1214 } -1215 $find-matching-primitive:next-primitive: -1216 # curr = curr->next -1217 8b/-> *(ecx+0x1c) 1/r32/ecx # Primitive-next -1218 eb/jump loop/disp8 -1219 } -1220 # return null -1221 b8/copy-to-eax 0/imm32 -1222 $find-matching-primitive:end: -1223 # . restore registers -1224 59/pop-to-ecx -1225 # . epilogue -1226 89/<- %esp 5/r32/ebp -1227 5d/pop-to-ebp -1228 c3/return -1229 -1230 mu-stmt-matches-function?: # stmt : (address statement), function : (address opcode-info) => result/eax : boolean -1231 # . prologue -1232 55/push-ebp -1233 89/<- %ebp 4/r32/esp -1234 # . save registers -1235 51/push-ecx -1236 # return primitive->name == stmt->operation -1237 8b/-> *(ebp+8) 1/r32/ecx -1238 8b/-> *(ebp+0xc) 0/r32/eax -1239 (string-equal? *ecx *eax) # => eax -1240 $mu-stmt-matches-function?:end: -1241 # . restore registers -1242 59/pop-to-ecx -1243 # . epilogue -1244 89/<- %esp 5/r32/ebp -1245 5d/pop-to-ebp -1246 c3/return -1247 -1248 mu-stmt-matches-primitive?: # stmt : (address statement), primitive : (address primitive) => result/eax : boolean -1249 # A mu stmt matches a primitive if the name matches, all the inout vars -1250 # match, and all the output vars match. -1251 # Vars match if types match and registers match. -1252 # In addition, a stmt output matches a primitive's output if types match -1253 # and the primitive has a wildcard register. -1254 # . prologue -1255 55/push-ebp -1256 89/<- %ebp 4/r32/esp -1257 # . save registers -1258 51/push-ecx -1259 52/push-edx -1260 53/push-ebx -1261 56/push-esi -1262 57/push-edi -1263 # ecx = stmt -1264 8b/-> *(ebp+8) 1/r32/ecx -1265 # edx = primitive -1266 8b/-> *(ebp+0xc) 2/r32/edx -1267 { -1268 $mu-stmt-matches-primitive?:check-name: -1269 # if (primitive->name != stmt->operation) return false -1270 (string-equal? *ecx *edx) # => eax -1271 3d/compare-eax-and 0/imm32 -1272 75/jump-if-not-equal break/disp8 -1273 b8/copy-to-eax 0/imm32 -1274 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1275 } -1276 $mu-stmt-matches-primitive?:check-inouts: -1277 # curr = stmt->inouts -1278 8b/-> *(ecx+4) 6/r32/esi # Stmt-inouts -1279 # curr2 = primitive->inouts -1280 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -1281 { -1282 # if (curr == 0) return (curr2 == 0) -1283 { -1284 81 7/subop/compare %esi 0/imm32 -1285 75/jump-if-not-equal break/disp8 -1286 { -1287 81 7/subop/compare %edi 0/imm32 -1288 75/jump-if-not-equal break/disp8 -1289 # return true -1290 b8/copy-to-eax 1/imm32 -1291 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1292 } -1293 # return false -1294 b8/copy-to-eax 0/imm32 -1295 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1296 } -1297 # if (curr2 == 0) return false -1298 { -1299 81 7/subop/compare %edi 0/imm32 -1300 75/jump-if-not-equal break/disp8 -1301 b8/copy-to-eax 0/imm32 -1302 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1303 } -1304 # if (curr != curr2) return false -1305 { -1306 (operand-matches-primitive? *esi *edi) # => eax -1307 3d/compare-eax-and 0/imm32 -1308 75/jump-if-not-equal break/disp8 -1309 b8/copy-to-eax 0/imm32 -1310 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1311 } -1312 # curr=curr->next -1313 8b/-> *(ecx+4) 1/r32/ecx # Operand-next -1314 # curr2=curr2->next -1315 8b/-> *(edx+4) 2/r32/edx # Operand-next -1316 } -1317 $mu-stmt-matches-primitive?:check-outputs: -1318 # ecx = stmt -1319 8b/-> *(ebp+8) 1/r32/ecx -1320 # edx = primitive -1321 8b/-> *(ebp+0xc) 2/r32/edx -1322 # curr = stmt->outputs -1323 8b/-> *(ecx+8) 6/r32/esi # Stmt-outputs -1324 # curr2 = primitive->outputs -1325 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -1326 { -1327 # if (curr == 0) return (curr2 == 0) -1328 { -1329 81 7/subop/compare %esi 0/imm32 -1330 75/jump-if-not-equal break/disp8 -1331 { -1332 81 7/subop/compare %edi 0/imm32 -1333 75/jump-if-not-equal break/disp8 -1334 # return true -1335 b8/copy-to-eax 1/imm32 -1336 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1337 } -1338 # return false -1339 b8/copy-to-eax 0/imm32 -1340 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1341 } -1342 # if (curr2 == 0) return false -1343 { -1344 81 7/subop/compare %edi 0/imm32 -1345 75/jump-if-not-equal break/disp8 -1346 b8/copy-to-eax 0/imm32 -1347 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1348 } -1349 # if (curr != curr2) return false -1350 { -1351 (output-operand-matches-primitive? *esi *edi) # => eax -1352 3d/compare-eax-and 0/imm32 -1353 75/jump-if-not-equal break/disp8 -1354 b8/copy-to-eax 0/imm32 -1355 e9/jump $mu-stmt-matches-primitive?:end/disp32 -1356 } -1357 # curr=curr->next -1358 8b/-> *(ecx+4) 1/r32/ecx # Operand-next -1359 # curr2=curr2->next -1360 8b/-> *(edx+4) 2/r32/edx # Operand-next -1361 } -1362 $mu-stmt-matches-primitive?:return-true: -1363 b8/copy-to-eax 1/imm32 -1364 $mu-stmt-matches-primitive?:end: -1365 # . restore registers -1366 5f/pop-to-edi -1367 5e/pop-to-esi -1368 5b/pop-to-ebx -1369 5a/pop-to-edx -1370 59/pop-to-ecx -1371 # . epilogue -1372 89/<- %esp 5/r32/ebp -1373 5d/pop-to-ebp -1374 c3/return -1375 -1376 operand-matches-primitive?: # var1 : (address var), var2 : (address var) => result/eax : boolean -1377 # . prologue -1378 55/push-ebp -1379 89/<- %ebp 4/r32/esp -1380 # . save registers -1381 56/push-esi -1382 57/push-edi -1383 # esi = var1 -1384 8b/-> *(ebp+8) 6/r32/esi -1385 # edi = var2 -1386 8b/-> *(ebp+0xc) 7/r32/edi -1387 # if (var1->type != var2->type) return false -1388 # if (var1->register != var1->register) return false -1389 { -1390 # if addresses are equal, don't return here -1391 8b/-> *(esi+0x10) 0/r32/eax -1392 39/compare *(edi+0x10) 0/r32/eax -1393 74/jump-if-equal break/disp8 -1394 # if either address is 0, return false -1395 3d/compare-eax-and 0/imm32 -1396 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var1->register to result -1397 81 7/subop/compare *(edi+0x10) 0/imm32 -1398 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var1->register to result -1399 # if string contents don't match, return false -1400 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register -1401 3d/compare-eax-and 0/imm32 -1402 b8/copy-to-eax 0/imm32/false -1403 74/jump-if-equal $operand-matches-primitive?:end/disp8 -1404 } -1405 # return true -1406 b8/copy-to-eax 1/imm32/true -1407 $operand-matches-primitive?:end: -1408 # . restore registers -1409 5f/pop-to-edi -1410 5e/pop-to-esi -1411 # . epilogue -1412 89/<- %esp 5/r32/ebp -1413 5d/pop-to-ebp -1414 c3/return -1415 -1416 # like operand-matches-primitive? but also handles "*" register in primitive -1417 output-operand-matches-primitive?: # var : (address var), primout-var : (address var) => result/eax : boolean -1418 # . prologue -1419 55/push-ebp -1420 89/<- %ebp 4/r32/esp -1421 # . save registers -1422 56/push-esi -1423 57/push-edi -1424 # esi = var -1425 8b/-> *(ebp+8) 6/r32/esi -1426 # edi = primout-var -1427 8b/-> *(ebp+0xc) 7/r32/edi -1428 # if (var->type != primout-var->type) return false -1429 # return false if var->register doesn't match primout-var->register -1430 { -1431 # if addresses are equal, don't return here -1432 8b/-> *(esi+0x10) 0/r32/eax -1433 39/compare *(edi+0x10) 0/r32/eax -1434 74/jump-if-equal break/disp8 -1435 # if either address is 0, return false -1436 3d/compare-eax-and 0/imm32 -1437 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -1438 81 7/subop/compare *(edi+0x10) 0/imm32 -1439 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -1440 # if primout-var->register is "*", return true -1441 (string-equal? *(edi+0x10) "*") # Var-register -1442 3d/compare-eax-and 0/imm32 -1443 b8/copy-to-eax 1/imm32/true -1444 75/jump-if-not-equal $operand-matches-primitive?:end/disp8 + 996 50/push-eax + 997 51/push-ecx + 998 # ecx = primitive + 999 8b/-> *(ebp+0x14) 1/r32/ecx +1000 # emit primitive name +1001 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name +1002 # emit rm32 if necessary +1003 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt +1004 #? # emit r32 if necessary +1005 #? (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt +1006 #? # emit imm32 if necessary +1007 #? (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt +1008 $emit-subx-primitive:end: +1009 # . restore registers +1010 59/pop-to-ecx +1011 58/pop-to-eax +1012 # . epilogue +1013 89/<- %esp 5/r32/ebp +1014 5d/pop-to-ebp +1015 c3/return +1016 +1017 emit-subx-rm32: # out : (address buffered-file), l : arg-location, stmt : (address statement) +1018 # . prologue +1019 55/push-ebp +1020 89/<- %ebp 4/r32/esp +1021 # . save registers +1022 50/push-eax +1023 # if (l == 0) return +1024 81 7/subop/compare *(ebp+0xc) 0/imm32 +1025 74/jump-if-equal $emit-subx-rm32:end/disp8 +1026 # +1027 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax +1028 (emit-subx-call-operand *(ebp+8) %eax) # out, var +1029 $emit-subx-rm32:end: +1030 # . restore registers +1031 58/pop-to-eax +1032 # . epilogue +1033 89/<- %esp 5/r32/ebp +1034 5d/pop-to-ebp +1035 c3/return +1036 +1037 get-stmt-operand-from-arg-location: # stmt : (address statement), l : arg-location -> var/eax : (address variable) +1038 # . prologue +1039 55/push-ebp +1040 89/<- %ebp 4/r32/esp +1041 # . save registers +1042 51/push-ecx +1043 # eax = l +1044 8b/-> *(ebp+0xc) 0/r32/eax +1045 # ecx = stmt +1046 8b/-> *(ebp+8) 1/r32/ecx +1047 # if (l == 1) return stmt->inouts->var +1048 { +1049 3d/compare-eax-and 1/imm32 +1050 75/jump-if-not-equal break/disp8 +1051 $get-stmt-operand-from-arg-location:1: +1052 8b/-> *(ecx+4) 0/r32/eax # Stmt-inouts +1053 8b/-> *eax 0/r32/eax # Operand-var +1054 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +1055 } +1056 # if (l == 2) return stmt->inouts->next->var +1057 { +1058 3d/compare-eax-and 2/imm32 +1059 75/jump-if-not-equal break/disp8 +1060 $get-stmt-operand-from-arg-location:2: +1061 8b/-> *(ecx+4) 0/r32/eax # Stmt-inouts +1062 8b/-> *(eax+4) 0/r32/eax # Operand-next +1063 8b/-> *eax 0/r32/eax # Operand-var +1064 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +1065 } +1066 # if (l == 3) return stmt->outputs +1067 { +1068 3d/compare-eax-and 3/imm32 +1069 75/jump-if-not-equal break/disp8 +1070 $get-stmt-operand-from-arg-location:3: +1071 8b/-> *(ecx+8) 0/r32/eax # Stmt-outputs +1072 8b/-> *eax 0/r32/eax # Operand-var +1073 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +1074 } +1075 # abort +1076 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +1077 $get-stmt-operand-from-arg-location:end: +1078 # . restore registers +1079 59/pop-to-ecx +1080 # . epilogue +1081 89/<- %esp 5/r32/ebp +1082 5d/pop-to-ebp +1083 c3/return +1084 +1085 $get-stmt-operand-from-arg-location:abort: +1086 # error("invalid arg-location " eax) +1087 (write-buffered Stderr "invalid arg-location ") +1088 (print-int32-buffered Stderr %eax) +1089 (write-buffered Stderr "\n") +1090 (flush Stderr) +1091 # . syscall(exit, 1) +1092 bb/copy-to-ebx 1/imm32 +1093 b8/copy-to-eax 1/imm32/exit +1094 cd/syscall 0x80/imm8 +1095 # never gets here +1096 +1097 emit-subx-r32: # out : (address buffered-file), l : arg-location, stmt : (address statement) +1098 # . prologue +1099 55/push-ebp +1100 89/<- %ebp 4/r32/esp +1101 # . save registers +1102 50/push-eax +1103 51/push-ecx +1104 # location/ecx : enum = primitive->subx-r32 +1105 # if (location == 0) return +1106 # var/ecx : var = get-operand(stmt, primitive->subx-rm32) +1107 # emit-subx-call-operand(out, var) +1108 $emit-subx-r32:end: +1109 # . restore registers +1110 59/pop-to-ecx +1111 58/pop-to-eax +1112 # . epilogue +1113 89/<- %esp 5/r32/ebp +1114 5d/pop-to-ebp +1115 c3/return +1116 +1117 emit-subx-imm32: # out : (address buffered-file), l : arg-location, stmt : (address statement) +1118 # . prologue +1119 55/push-ebp +1120 89/<- %ebp 4/r32/esp +1121 # . save registers +1122 50/push-eax +1123 51/push-ecx +1124 # var/ecx : var = get-operand(stmt, primitive->subx-rm32) +1125 # emit-subx-call-operand(out, var) +1126 $emit-subx-imm32:end: +1127 # . restore registers +1128 59/pop-to-ecx +1129 58/pop-to-eax +1130 # . epilogue +1131 89/<- %esp 5/r32/ebp +1132 5d/pop-to-ebp +1133 c3/return +1134 +1135 emit-subx-call: # out : (address buffered-file), stmt : (address statement), vars : (address variable), callee : (address function) +1136 # . prologue +1137 55/push-ebp +1138 89/<- %ebp 4/r32/esp +1139 # . save registers +1140 50/push-eax +1141 51/push-ecx +1142 # +1143 (write-buffered *(ebp+8) "(") +1144 # - emit function name +1145 8b/-> *(ebp+0x14) 1/r32/ecx +1146 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name +1147 # - emit arguments +1148 # var curr/ecx : (list var) = stmt->inouts +1149 8b/-> *(ebp+0xc) 1/r32/ecx +1150 8b/-> *(ecx+4) 1/r32/ecx # Stmt-inouts +1151 { +1152 # if (curr == null) break +1153 81 7/subop/compare %ecx 0/imm32 +1154 74/jump-if-equal break/disp8 +1155 # +1156 (emit-subx-call-operand *(ebp+8) *ecx) +1157 # curr = curr->next +1158 8b/-> *(ecx+4) 1/r32/ecx +1159 } +1160 # +1161 (write-buffered *(ebp+8) ")") +1162 $emit-subx-call:end: +1163 # . restore registers +1164 59/pop-to-ecx +1165 58/pop-to-eax +1166 # . epilogue +1167 89/<- %esp 5/r32/ebp +1168 5d/pop-to-ebp +1169 c3/return +1170 +1171 emit-subx-call-operand: # out : (address buffered-file), operand : (address variable) +1172 # . prologue +1173 55/push-ebp +1174 89/<- %ebp 4/r32/esp +1175 # . save registers +1176 50/push-eax +1177 # eax = operand +1178 8b/-> *(ebp+0xc) 0/r32/eax +1179 # if (operand->register) emit "%__" +1180 { +1181 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +1182 74/jump-if-equal break/disp8 +1183 $emit-subx-call-operand:register: +1184 (write-buffered *(ebp+8) " %") +1185 (write-buffered *(ebp+8) *(eax+0x10)) # Var-register +1186 } +1187 # else if (operand->stack-offset) emit "*(ebp+__)" +1188 { +1189 81 7/subop/compare *(eax+0xc) 0/imm32 # Var-stack-offset +1190 74/jump-if-equal break/disp8 +1191 $emit-subx-call-operand:stack: +1192 (write-buffered *(ebp+8) Space) +1193 (write-buffered *(ebp+8) "*(ebp+") +1194 8b/-> *(ebp+0xc) 0/r32/eax +1195 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-stack-offset +1196 (write-buffered *(ebp+8) ")") +1197 } +1198 $emit-subx-call-operand:end: +1199 # . restore registers +1200 58/pop-to-eax +1201 # . epilogue +1202 89/<- %esp 5/r32/ebp +1203 5d/pop-to-ebp +1204 c3/return +1205 +1206 find-matching-function: # functions : (address function), stmt : (address statement) -> result/eax : (address function) +1207 # . prologue +1208 55/push-ebp +1209 89/<- %ebp 4/r32/esp +1210 # . save registers +1211 51/push-ecx +1212 # var curr/ecx : (address function) = functions +1213 8b/-> *(ebp+8) 1/r32/ecx +1214 { +1215 # if (curr == null) break +1216 81 7/subop/compare %ecx 0/imm32 +1217 74/jump-if-equal break/disp8 +1218 # if match(curr, stmt) return curr +1219 { +1220 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +1221 3d/compare-eax-and 0/imm32 +1222 74/jump-if-equal break/disp8 +1223 89/<- %eax 1/r32/ecx +1224 eb/jump $find-matching-function:end/disp8 +1225 } +1226 # curr = curr->next +1227 8b/-> *(ecx+0x10) 1/r32/ecx # Function-next +1228 eb/jump loop/disp8 +1229 } +1230 # return null +1231 b8/copy-to-eax 0/imm32 +1232 $find-matching-function:end: +1233 # . restore registers +1234 59/pop-to-ecx +1235 # . epilogue +1236 89/<- %esp 5/r32/ebp +1237 5d/pop-to-ebp +1238 c3/return +1239 +1240 find-matching-primitive: # primitives : (address primitive), stmt : (address statement) -> result/eax : (address primitive) +1241 # . prologue +1242 55/push-ebp +1243 89/<- %ebp 4/r32/esp +1244 # . save registers +1245 51/push-ecx +1246 # var curr/ecx : (address primitive) = primitives +1247 8b/-> *(ebp+8) 1/r32/ecx +1248 { +1249 $find-matching-primitive:loop: +1250 # if (curr == null) break +1251 81 7/subop/compare %ecx 0/imm32 +1252 74/jump-if-equal break/disp8 +1253 # if match(curr, stmt) return curr +1254 { +1255 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +1256 3d/compare-eax-and 0/imm32 +1257 74/jump-if-equal break/disp8 +1258 89/<- %eax 1/r32/ecx +1259 eb/jump $find-matching-function:end/disp8 +1260 } +1261 $find-matching-primitive:next-primitive: +1262 # curr = curr->next +1263 8b/-> *(ecx+0x1c) 1/r32/ecx # Primitive-next +1264 eb/jump loop/disp8 +1265 } +1266 # return null +1267 b8/copy-to-eax 0/imm32 +1268 $find-matching-primitive:end: +1269 # . restore registers +1270 59/pop-to-ecx +1271 # . epilogue +1272 89/<- %esp 5/r32/ebp +1273 5d/pop-to-ebp +1274 c3/return +1275 +1276 mu-stmt-matches-function?: # stmt : (address statement), function : (address opcode-info) => result/eax : boolean +1277 # . prologue +1278 55/push-ebp +1279 89/<- %ebp 4/r32/esp +1280 # . save registers +1281 51/push-ecx +1282 # return primitive->name == stmt->operation +1283 8b/-> *(ebp+8) 1/r32/ecx +1284 8b/-> *(ebp+0xc) 0/r32/eax +1285 (string-equal? *ecx *eax) # => eax +1286 $mu-stmt-matches-function?:end: +1287 # . restore registers +1288 59/pop-to-ecx +1289 # . epilogue +1290 89/<- %esp 5/r32/ebp +1291 5d/pop-to-ebp +1292 c3/return +1293 +1294 mu-stmt-matches-primitive?: # stmt : (address statement), primitive : (address primitive) => result/eax : boolean +1295 # A mu stmt matches a primitive if the name matches, all the inout vars +1296 # match, and all the output vars match. +1297 # Vars match if types match and registers match. +1298 # In addition, a stmt output matches a primitive's output if types match +1299 # and the primitive has a wildcard register. +1300 # . prologue +1301 55/push-ebp +1302 89/<- %ebp 4/r32/esp +1303 # . save registers +1304 51/push-ecx +1305 52/push-edx +1306 53/push-ebx +1307 56/push-esi +1308 57/push-edi +1309 # ecx = stmt +1310 8b/-> *(ebp+8) 1/r32/ecx +1311 # edx = primitive +1312 8b/-> *(ebp+0xc) 2/r32/edx +1313 { +1314 $mu-stmt-matches-primitive?:check-name: +1315 # if (primitive->name != stmt->operation) return false +1316 (string-equal? *ecx *edx) # => eax +1317 3d/compare-eax-and 0/imm32 +1318 75/jump-if-not-equal break/disp8 +1319 b8/copy-to-eax 0/imm32 +1320 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1321 } +1322 $mu-stmt-matches-primitive?:check-inouts: +1323 # curr = stmt->inouts +1324 8b/-> *(ecx+4) 6/r32/esi # Stmt-inouts +1325 # curr2 = primitive->inouts +1326 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +1327 { +1328 # if (curr == 0) return (curr2 == 0) +1329 { +1330 81 7/subop/compare %esi 0/imm32 +1331 75/jump-if-not-equal break/disp8 +1332 { +1333 81 7/subop/compare %edi 0/imm32 +1334 75/jump-if-not-equal break/disp8 +1335 # return true +1336 b8/copy-to-eax 1/imm32 +1337 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1338 } +1339 # return false +1340 b8/copy-to-eax 0/imm32 +1341 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1342 } +1343 # if (curr2 == 0) return false +1344 { +1345 81 7/subop/compare %edi 0/imm32 +1346 75/jump-if-not-equal break/disp8 +1347 b8/copy-to-eax 0/imm32 +1348 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1349 } +1350 # if (curr != curr2) return false +1351 { +1352 (operand-matches-primitive? *esi *edi) # => eax +1353 3d/compare-eax-and 0/imm32 +1354 75/jump-if-not-equal break/disp8 +1355 b8/copy-to-eax 0/imm32 +1356 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1357 } +1358 # curr=curr->next +1359 8b/-> *(ecx+4) 1/r32/ecx # Operand-next +1360 # curr2=curr2->next +1361 8b/-> *(edx+4) 2/r32/edx # Operand-next +1362 } +1363 $mu-stmt-matches-primitive?:check-outputs: +1364 # ecx = stmt +1365 8b/-> *(ebp+8) 1/r32/ecx +1366 # edx = primitive +1367 8b/-> *(ebp+0xc) 2/r32/edx +1368 # curr = stmt->outputs +1369 8b/-> *(ecx+8) 6/r32/esi # Stmt-outputs +1370 # curr2 = primitive->outputs +1371 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +1372 { +1373 # if (curr == 0) return (curr2 == 0) +1374 { +1375 81 7/subop/compare %esi 0/imm32 +1376 75/jump-if-not-equal break/disp8 +1377 { +1378 81 7/subop/compare %edi 0/imm32 +1379 75/jump-if-not-equal break/disp8 +1380 # return true +1381 b8/copy-to-eax 1/imm32 +1382 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1383 } +1384 # return false +1385 b8/copy-to-eax 0/imm32 +1386 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1387 } +1388 # if (curr2 == 0) return false +1389 { +1390 81 7/subop/compare %edi 0/imm32 +1391 75/jump-if-not-equal break/disp8 +1392 b8/copy-to-eax 0/imm32 +1393 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1394 } +1395 # if (curr != curr2) return false +1396 { +1397 (output-operand-matches-primitive? *esi *edi) # => eax +1398 3d/compare-eax-and 0/imm32 +1399 75/jump-if-not-equal break/disp8 +1400 b8/copy-to-eax 0/imm32 +1401 e9/jump $mu-stmt-matches-primitive?:end/disp32 +1402 } +1403 # curr=curr->next +1404 8b/-> *(ecx+4) 1/r32/ecx # Operand-next +1405 # curr2=curr2->next +1406 8b/-> *(edx+4) 2/r32/edx # Operand-next +1407 } +1408 $mu-stmt-matches-primitive?:return-true: +1409 b8/copy-to-eax 1/imm32 +1410 $mu-stmt-matches-primitive?:end: +1411 # . restore registers +1412 5f/pop-to-edi +1413 5e/pop-to-esi +1414 5b/pop-to-ebx +1415 5a/pop-to-edx +1416 59/pop-to-ecx +1417 # . epilogue +1418 89/<- %esp 5/r32/ebp +1419 5d/pop-to-ebp +1420 c3/return +1421 +1422 operand-matches-primitive?: # var1 : (address var), var2 : (address var) => result/eax : boolean +1423 # . prologue +1424 55/push-ebp +1425 89/<- %ebp 4/r32/esp +1426 # . save registers +1427 56/push-esi +1428 57/push-edi +1429 # esi = var1 +1430 8b/-> *(ebp+8) 6/r32/esi +1431 # edi = var2 +1432 8b/-> *(ebp+0xc) 7/r32/edi +1433 # if (var1->type != var2->type) return false +1434 # if (var1->register != var1->register) return false +1435 { +1436 # if addresses are equal, don't return here +1437 8b/-> *(esi+0x10) 0/r32/eax +1438 39/compare *(edi+0x10) 0/r32/eax +1439 74/jump-if-equal break/disp8 +1440 # if either address is 0, return false +1441 3d/compare-eax-and 0/imm32 +1442 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var1->register to result +1443 81 7/subop/compare *(edi+0x10) 0/imm32 +1444 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var1->register to result 1445 # if string contents don't match, return false 1446 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register 1447 3d/compare-eax-and 0/imm32 @@ -1491,7 +1492,7 @@ if ('onhashchange' in window) { 1450 } 1451 # return true 1452 b8/copy-to-eax 1/imm32/true -1453 $output-operand-matches-primitive?:end: +1453 $operand-matches-primitive?:end: 1454 # . restore registers 1455 5f/pop-to-edi 1456 5e/pop-to-esi @@ -1500,443 +1501,601 @@ if ('onhashchange' in window) { 1459 5d/pop-to-ebp 1460 c3/return 1461 -1462 test-emit-subx-statement-primitive: -1463 # Primitive operation on a variable on the stack. -1464 # increment foo -1465 # => -1466 # ff 0/subop/increment *(ebp-8) -1467 # -1468 # There's a variable on the var stack as follows: -1469 # name: 'foo' -1470 # type: int -1471 # stack-offset: -8 -1472 # -1473 # There's a primitive with this info: -1474 # name: 'increment' -1475 # inouts: int/mem -1476 # value: 'ff 0/subop/increment' -1477 # -1478 # There's nothing in functions. -1479 # -1480 # . prologue -1481 55/push-ebp -1482 89/<- %ebp 4/r32/esp -1483 # setup -1484 (clear-stream _test-output-stream) -1485 (clear-stream _test-output-buffered-file->buffer) -1486 # var-foo/ecx : var -1487 68/push 0/imm32/no-register -1488 68/push -8/imm32/stack-offset -1489 68/push 1/imm32/block-depth -1490 68/push 1/imm32/type-int -1491 68/push "foo"/imm32 -1492 89/<- %ecx 4/r32/esp -1493 #? $aa-var-in-ecx: -1494 # vars/edx : (stack 1) -1495 51/push-ecx/var-foo -1496 68/push 1/imm32/data-length -1497 68/push 1/imm32/top -1498 89/<- %edx 4/r32/esp -1499 #? $aa-vars-in-edx: -1500 # operand/ebx : (list var) -1501 68/push 0/imm32/next -1502 51/push-ecx/var-foo -1503 89/<- %ebx 4/r32/esp -1504 #? $aa-stmt-operand-in-ebx: -1505 # stmt/esi : statement -1506 68/push 0/imm32/next -1507 68/push 0/imm32/outputs -1508 53/push-ebx/operands -1509 68/push "increment"/imm32/operation -1510 89/<- %esi 4/r32/esp -1511 #? $aa-stmt-in-esi: -1512 # primitives/ebx : primitive -1513 68/push 0/imm32/next -1514 68/push 0/imm32/no-imm32 -1515 68/push 0/imm32/no-r32 -1516 68/push 1/imm32/rm32-is-first-inout -1517 68/push "ff 0/subop/increment"/imm32/subx-name -1518 68/push 0/imm32/outputs -1519 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -1520 68/push "increment"/imm32/name -1521 89/<- %ebx 4/r32/esp -1522 $aa-primitive-in-ebx: -1523 # convert -1524 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1525 (flush _test-output-buffered-file) -1526 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1532 # check output -1533 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive/0") -1534 # . reclaim locals -1535 81 0/subop/add %esp 0x48/imm32 -1536 # . epilogue -1537 89/<- %esp 5/r32/ebp -1538 5d/pop-to-ebp -1539 c3/return -1540 -1541 test-emit-subx-statement-primitive-register: -1542 # Primitive operation on a variable in a register. -1543 # foo <- increment -1544 # => -1545 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1546 # -1547 # There's a variable on the var stack as follows: -1548 # name: 'foo' -1549 # type: int -1550 # register: 'eax' -1551 # -1552 # There's a primitive with this info: -1553 # name: 'increment' -1554 # out: int/reg -1555 # value: 'ff 0/subop/increment' -1556 # -1557 # There's nothing in functions. -1558 # -1559 # . prologue -1560 55/push-ebp -1561 89/<- %ebp 4/r32/esp -1562 # setup -1563 (clear-stream _test-output-stream) -1564 (clear-stream _test-output-buffered-file->buffer) -1565 # var-foo/ecx : var in eax -1566 68/push "eax"/imm32/register -1567 68/push 0/imm32/no-stack-offset -1568 68/push 1/imm32/block-depth -1569 68/push 1/imm32/type-int -1570 68/push "foo"/imm32 -1571 89/<- %ecx 4/r32/esp -1572 # vars/edx : (stack 1) -1573 51/push-ecx/var-foo -1574 68/push 1/imm32/data-length -1575 68/push 1/imm32/top -1576 89/<- %edx 4/r32/esp -1577 # operand/ebx : (list var) -1578 68/push 0/imm32/next -1579 51/push-ecx/var-foo -1580 89/<- %ebx 4/r32/esp -1581 # stmt/esi : statement -1582 68/push 0/imm32/next -1583 53/push-ebx/outputs -1584 68/push 0/imm32/inouts -1585 68/push "increment"/imm32/operation -1586 89/<- %esi 4/r32/esp -1587 # formal-var/ebx : var in any register -1588 68/push Any-register/imm32 -1589 68/push 0/imm32/no-stack-offset -1590 68/push 1/imm32/block-depth -1591 68/push 1/imm32/type-int -1592 68/push "dummy"/imm32 -1593 89/<- %ebx 4/r32/esp -1594 # operand/ebx : (list var) -1595 68/push 0/imm32/next -1596 53/push-ebx/formal-var -1597 89/<- %ebx 4/r32/esp -1598 # primitives/ebx : primitive -1599 68/push 0/imm32/next -1600 68/push 0/imm32/no-imm32 -1601 68/push 0/imm32/no-r32 -1602 68/push 3/imm32/rm32-in-first-output -1603 68/push "ff 0/subop/increment"/imm32/subx-name -1604 53/push-ebx/outputs -1605 68/push 0/imm32/inouts -1606 68/push "increment"/imm32/name -1607 89/<- %ebx 4/r32/esp -1608 # convert -1609 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1610 (flush _test-output-buffered-file) -1611 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1617 # check output -1618 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register/0") -1619 # . reclaim locals -1620 81 0/subop/add %esp 0x48/imm32 -1621 # . epilogue -1622 89/<- %esp 5/r32/ebp -1623 5d/pop-to-ebp -1624 c3/return -1625 -1626 test-emit-subx-statement-select-primitive: -1627 # Select the right primitive between overloads. -1628 # foo <- increment -1629 # => -1630 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1631 # -1632 # There's a variable on the var stack as follows: -1633 # name: 'foo' -1634 # type: int -1635 # register: 'eax' -1636 # -1637 # There's two primitives, as follows: -1638 # - name: 'increment' -1639 # out: int/reg -1640 # value: 'ff 0/subop/increment' -1641 # - name: 'increment' -1642 # inout: int/mem -1643 # value: 'ff 0/subop/increment' -1644 # -1645 # There's nothing in functions. -1646 # -1647 # . prologue -1648 55/push-ebp -1649 89/<- %ebp 4/r32/esp -1650 # setup -1651 (clear-stream _test-output-stream) -1652 (clear-stream _test-output-buffered-file->buffer) -1653 # var-foo/ecx : var in eax -1654 68/push "eax"/imm32/register -1655 68/push 0/imm32/no-stack-offset -1656 68/push 1/imm32/block-depth -1657 68/push 1/imm32/type-int -1658 68/push "foo"/imm32 -1659 89/<- %ecx 4/r32/esp -1660 # vars/edx : (stack 1) -1661 51/push-ecx/var-foo -1662 68/push 1/imm32/data-length -1663 68/push 1/imm32/top -1664 89/<- %edx 4/r32/esp -1665 # real-outputs/edi : (list var) -1666 68/push 0/imm32/next -1667 51/push-ecx/var-foo -1668 89/<- %edi 4/r32/esp -1669 # stmt/esi : statement -1670 68/push 0/imm32/next -1671 57/push-edi/outputs -1672 68/push 0/imm32/inouts -1673 68/push "increment"/imm32/operation -1674 89/<- %esi 4/r32/esp -1675 # formal-var/ebx : var in any register -1676 68/push Any-register/imm32 -1677 68/push 0/imm32/no-stack-offset -1678 68/push 1/imm32/block-depth -1679 68/push 1/imm32/type-int -1680 68/push "dummy"/imm32 -1681 89/<- %ebx 4/r32/esp -1682 # formal-outputs/ebx : (list var) -1683 68/push 0/imm32/next -1684 53/push-ebx/formal-var -1685 89/<- %ebx 4/r32/esp -1686 # primitive1/ebx : primitive -1687 68/push 0/imm32/next -1688 68/push 0/imm32/no-imm32 -1689 68/push 0/imm32/no-r32 -1690 68/push 3/imm32/rm32-in-first-output -1691 68/push "ff 0/subop/increment"/imm32/subx-name -1692 53/push-ebx/outputs/formal-outputs -1693 68/push 0/imm32/inouts -1694 68/push "increment"/imm32/name -1695 89/<- %ebx 4/r32/esp -1696 # primitives/ebx : primitive -1697 53/push-ebx/next -1698 68/push 0/imm32/no-imm32 -1699 68/push 0/imm32/no-r32 -1700 68/push 1/imm32/rm32-is-first-inout -1701 68/push "ff 0/subop/increment"/imm32/subx-name -1702 68/push 0/imm32/outputs -1703 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -1704 68/push "increment"/imm32/name -1705 89/<- %ebx 4/r32/esp -1706 # convert -1707 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1708 (flush _test-output-buffered-file) -1709 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1715 # check output -1716 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive/0") -1717 # . reclaim locals -1718 81 0/subop/add %esp 0x48/imm32 -1719 # . epilogue -1720 89/<- %esp 5/r32/ebp -1721 5d/pop-to-ebp -1722 c3/return -1723 -1724 test-emit-subx-statement-select-primitive-2: -1725 # Select the right primitive between overloads. -1726 # foo <- increment -1727 # => -1728 # ff 0/subop/increment %eax # sub-optimal, but should suffice -1729 # -1730 # There's a variable on the var stack as follows: -1731 # name: 'foo' -1732 # type: int -1733 # register: 'eax' -1734 # -1735 # There's two primitives, as follows: -1736 # - name: 'increment' -1737 # out: int/reg -1738 # value: 'ff 0/subop/increment' -1739 # - name: 'increment' -1740 # inout: int/mem -1741 # value: 'ff 0/subop/increment' -1742 # -1743 # There's nothing in functions. -1744 # -1745 # . prologue -1746 55/push-ebp -1747 89/<- %ebp 4/r32/esp -1748 # setup -1749 (clear-stream _test-output-stream) -1750 (clear-stream _test-output-buffered-file->buffer) -1751 # var-foo/ecx : var in eax -1752 68/push "eax"/imm32/register -1753 68/push 0/imm32/no-stack-offset -1754 68/push 1/imm32/block-depth -1755 68/push 1/imm32/type-int -1756 68/push "foo"/imm32 -1757 89/<- %ecx 4/r32/esp -1758 # vars/edx : (stack 1) -1759 51/push-ecx/var-foo -1760 68/push 1/imm32/data-length -1761 68/push 1/imm32/top -1762 89/<- %edx 4/r32/esp -1763 # inouts/edi : (list var) -1764 68/push 0/imm32/next -1765 51/push-ecx/var-foo -1766 89/<- %edi 4/r32/esp -1767 # stmt/esi : statement -1768 68/push 0/imm32/next -1769 68/push 0/imm32/outputs -1770 57/push-edi/inouts -1771 68/push "increment"/imm32/operation -1772 89/<- %esi 4/r32/esp -1773 # formal-var/ebx : var in any register -1774 68/push Any-register/imm32 -1775 68/push 0/imm32/no-stack-offset -1776 68/push 1/imm32/block-depth -1777 68/push 1/imm32/type-int -1778 68/push "dummy"/imm32 -1779 89/<- %ebx 4/r32/esp -1780 # operand/ebx : (list var) -1781 68/push 0/imm32/next -1782 53/push-ebx/formal-var -1783 89/<- %ebx 4/r32/esp -1784 # primitive1/ebx : primitive -1785 68/push 0/imm32/next -1786 68/push 0/imm32/no-imm32 -1787 68/push 0/imm32/no-r32 -1788 68/push 3/imm32/rm32-in-first-output -1789 68/push "ff 0/subop/increment"/imm32/subx-name -1790 53/push-ebx/outputs/formal-outputs -1791 68/push 0/imm32/inouts -1792 68/push "increment"/imm32/name -1793 89/<- %ebx 4/r32/esp -1794 # primitives/ebx : primitive -1795 53/push-ebx/next -1796 68/push 0/imm32/no-imm32 -1797 68/push 0/imm32/no-r32 -1798 68/push 1/imm32/rm32-is-first-inout -1799 68/push "ff 0/subop/increment"/imm32/subx-name -1800 68/push 0/imm32/outputs -1801 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -1802 68/push "increment"/imm32/name -1803 89/<- %ebx 4/r32/esp -1804 # convert -1805 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) -1806 (flush _test-output-buffered-file) -1807 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1813 # check output -1814 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2/0") -1815 # . reclaim locals -1816 81 0/subop/add %esp 0x48/imm32 -1817 # . epilogue -1818 89/<- %esp 5/r32/ebp -1819 5d/pop-to-ebp -1820 c3/return -1821 -1822 test-emit-subx-statement-function-call: -1823 # Call a function on a variable on the stack. -1824 # f foo -1825 # => -1826 # (f2 *(ebp-8)) -1827 # (Changing the function name supports overloading in general, but here it -1828 # just serves to help disambiguate things.) -1829 # -1830 # There's a variable on the var stack as follows: -1831 # name: 'foo' -1832 # type: int -1833 # stack-offset: -8 -1834 # -1835 # There's nothing in primitives. -1836 # -1837 # There's a function with this info: -1838 # name: 'f' -1839 # inout: int/mem -1840 # value: 'f2' -1841 # -1842 # . prologue -1843 55/push-ebp -1844 89/<- %ebp 4/r32/esp -1845 # setup -1846 (clear-stream _test-output-stream) -1847 (clear-stream _test-output-buffered-file->buffer) -1848 # var-foo/ecx : var -1849 68/push 0/imm32/no-register -1850 68/push -8/imm32/stack-offset -1851 68/push 0/imm32/block-depth -1852 68/push 1/imm32/type-int -1853 68/push "foo"/imm32 -1854 89/<- %ecx 4/r32/esp -1855 # vars/edx = (stack 1) -1856 51/push-ecx/var-foo -1857 68/push 1/imm32/data-length -1858 68/push 1/imm32/top -1859 89/<- %edx 4/r32/esp -1860 # operands/esi : (list var) -1861 68/push 0/imm32/next -1862 51/push-ecx/var-foo -1863 89/<- %esi 4/r32/esp -1864 # stmt/esi : statement -1865 68/push 0/imm32/next -1866 68/push 0/imm32/outputs -1867 56/push-esi/inouts -1868 68/push "f"/imm32/operation -1869 89/<- %esi 4/r32/esp -1870 # functions/ebx : function -1871 68/push 0/imm32/next -1872 68/push 0/imm32/body -1873 68/push 0/imm32/outputs -1874 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -1875 68/push "f2"/imm32/subx-name -1876 68/push "f"/imm32/name -1877 89/<- %ebx 4/r32/esp -1878 # convert -1879 (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx) -1880 (flush _test-output-buffered-file) -1881 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1887 # check output -1888 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call/0") -1889 # . reclaim locals -1890 81 0/subop/add %esp 0x3c/imm32 -1891 # . epilogue -1892 89/<- %esp 5/r32/ebp -1893 5d/pop-to-ebp -1894 c3/return -1895 -1896 emit-subx-prologue: # out : (address buffered-file) -1897 # . prologue -1898 55/push-ebp -1899 89/<- %ebp 4/r32/esp -1900 # -1901 (write-buffered *(ebp+8) "# . prologue\n") -1902 (write-buffered *(ebp+8) "55/push-ebp\n") -1903 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") -1904 $emit-subx-prologue:end: -1905 # . epilogue -1906 89/<- %esp 5/r32/ebp -1907 5d/pop-to-ebp -1908 c3/return -1909 -1910 emit-subx-epilogue: # out : (address buffered-file) -1911 # . prologue -1912 55/push-ebp -1913 89/<- %ebp 4/r32/esp -1914 # -1915 (write-buffered *(ebp+8) "# . epilogue\n") -1916 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") -1917 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") -1918 (write-buffered *(ebp+8) "c3/return\n") -1919 $emit-subx-epilogue:end: -1920 # . epilogue -1921 89/<- %esp 5/r32/ebp -1922 5d/pop-to-ebp -1923 c3/return +1462 # like operand-matches-primitive? but also handles "*" register in primitive +1463 output-operand-matches-primitive?: # var : (address var), primout-var : (address var) => result/eax : boolean +1464 # . prologue +1465 55/push-ebp +1466 89/<- %ebp 4/r32/esp +1467 # . save registers +1468 56/push-esi +1469 57/push-edi +1470 # esi = var +1471 8b/-> *(ebp+8) 6/r32/esi +1472 # edi = primout-var +1473 8b/-> *(ebp+0xc) 7/r32/edi +1474 # if (var->type != primout-var->type) return false +1475 # return false if var->register doesn't match primout-var->register +1476 { +1477 # if addresses are equal, don't return here +1478 8b/-> *(esi+0x10) 0/r32/eax +1479 39/compare *(edi+0x10) 0/r32/eax +1480 74/jump-if-equal break/disp8 +1481 # if either address is 0, return false +1482 3d/compare-eax-and 0/imm32 +1483 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +1484 81 7/subop/compare *(edi+0x10) 0/imm32 +1485 74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +1486 # if primout-var->register is "*", return true +1487 (string-equal? *(edi+0x10) "*") # Var-register +1488 3d/compare-eax-and 0/imm32 +1489 b8/copy-to-eax 1/imm32/true +1490 75/jump-if-not-equal $operand-matches-primitive?:end/disp8 +1491 # if string contents don't match, return false +1492 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register +1493 3d/compare-eax-and 0/imm32 +1494 b8/copy-to-eax 0/imm32/false +1495 74/jump-if-equal $operand-matches-primitive?:end/disp8 +1496 } +1497 # return true +1498 b8/copy-to-eax 1/imm32/true +1499 $output-operand-matches-primitive?:end: +1500 # . restore registers +1501 5f/pop-to-edi +1502 5e/pop-to-esi +1503 # . epilogue +1504 89/<- %esp 5/r32/ebp +1505 5d/pop-to-ebp +1506 c3/return +1507 +1508 test-emit-subx-statement-primitive: +1509 # Primitive operation on a variable on the stack. +1510 # increment foo +1511 # => +1512 # ff 0/subop/increment *(ebp-8) +1513 # +1514 # There's a variable on the var stack as follows: +1515 # name: 'foo' +1516 # type: int +1517 # stack-offset: -8 +1518 # +1519 # There's a primitive with this info: +1520 # name: 'increment' +1521 # inouts: int/mem +1522 # value: 'ff 0/subop/increment' +1523 # +1524 # There's nothing in functions. +1525 # +1526 # . prologue +1527 55/push-ebp +1528 89/<- %ebp 4/r32/esp +1529 # setup +1530 (clear-stream _test-output-stream) +1531 (clear-stream _test-output-buffered-file->buffer) +1532 # var-foo/ecx : var +1533 68/push 0/imm32/no-register +1534 68/push -8/imm32/stack-offset +1535 68/push 1/imm32/block-depth +1536 68/push 1/imm32/type-int +1537 68/push "foo"/imm32 +1538 89/<- %ecx 4/r32/esp +1539 #? $aa-var-in-ecx: +1540 # vars/edx : (stack 1) +1541 51/push-ecx/var-foo +1542 68/push 1/imm32/data-length +1543 68/push 1/imm32/top +1544 89/<- %edx 4/r32/esp +1545 #? $aa-vars-in-edx: +1546 # operand/ebx : (list var) +1547 68/push 0/imm32/next +1548 51/push-ecx/var-foo +1549 89/<- %ebx 4/r32/esp +1550 #? $aa-stmt-operand-in-ebx: +1551 # stmt/esi : statement +1552 68/push 0/imm32/next +1553 68/push 0/imm32/outputs +1554 53/push-ebx/operands +1555 68/push "increment"/imm32/operation +1556 89/<- %esi 4/r32/esp +1557 #? $aa-stmt-in-esi: +1558 # primitives/ebx : primitive +1559 68/push 0/imm32/next +1560 68/push 0/imm32/no-imm32 +1561 68/push 0/imm32/no-r32 +1562 68/push 1/imm32/rm32-is-first-inout +1563 68/push "ff 0/subop/increment"/imm32/subx-name +1564 68/push 0/imm32/outputs +1565 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +1566 68/push "increment"/imm32/name +1567 89/<- %ebx 4/r32/esp +1568 $aa-primitive-in-ebx: +1569 # convert +1570 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1571 (flush _test-output-buffered-file) +1572 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1578 # check output +1579 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive/0") +1580 # . reclaim locals +1581 81 0/subop/add %esp 0x48/imm32 +1582 # . epilogue +1583 89/<- %esp 5/r32/ebp +1584 5d/pop-to-ebp +1585 c3/return +1586 +1587 test-emit-subx-statement-primitive-register: +1588 # Primitive operation on a variable in a register. +1589 # foo <- increment +1590 # => +1591 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1592 # +1593 # There's a variable on the var stack as follows: +1594 # name: 'foo' +1595 # type: int +1596 # register: 'eax' +1597 # +1598 # There's a primitive with this info: +1599 # name: 'increment' +1600 # out: int/reg +1601 # value: 'ff 0/subop/increment' +1602 # +1603 # There's nothing in functions. +1604 # +1605 # . prologue +1606 55/push-ebp +1607 89/<- %ebp 4/r32/esp +1608 # setup +1609 (clear-stream _test-output-stream) +1610 (clear-stream _test-output-buffered-file->buffer) +1611 # var-foo/ecx : var in eax +1612 68/push "eax"/imm32/register +1613 68/push 0/imm32/no-stack-offset +1614 68/push 1/imm32/block-depth +1615 68/push 1/imm32/type-int +1616 68/push "foo"/imm32 +1617 89/<- %ecx 4/r32/esp +1618 # vars/edx : (stack 1) +1619 51/push-ecx/var-foo +1620 68/push 1/imm32/data-length +1621 68/push 1/imm32/top +1622 89/<- %edx 4/r32/esp +1623 # operand/ebx : (list var) +1624 68/push 0/imm32/next +1625 51/push-ecx/var-foo +1626 89/<- %ebx 4/r32/esp +1627 # stmt/esi : statement +1628 68/push 0/imm32/next +1629 53/push-ebx/outputs +1630 68/push 0/imm32/inouts +1631 68/push "increment"/imm32/operation +1632 89/<- %esi 4/r32/esp +1633 # formal-var/ebx : var in any register +1634 68/push Any-register/imm32 +1635 68/push 0/imm32/no-stack-offset +1636 68/push 1/imm32/block-depth +1637 68/push 1/imm32/type-int +1638 68/push "dummy"/imm32 +1639 89/<- %ebx 4/r32/esp +1640 # operand/ebx : (list var) +1641 68/push 0/imm32/next +1642 53/push-ebx/formal-var +1643 89/<- %ebx 4/r32/esp +1644 # primitives/ebx : primitive +1645 68/push 0/imm32/next +1646 68/push 0/imm32/no-imm32 +1647 68/push 0/imm32/no-r32 +1648 68/push 3/imm32/rm32-in-first-output +1649 68/push "ff 0/subop/increment"/imm32/subx-name +1650 53/push-ebx/outputs +1651 68/push 0/imm32/inouts +1652 68/push "increment"/imm32/name +1653 89/<- %ebx 4/r32/esp +1654 # convert +1655 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1656 (flush _test-output-buffered-file) +1657 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1663 # check output +1664 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register/0") +1665 # . reclaim locals +1666 81 0/subop/add %esp 0x48/imm32 +1667 # . epilogue +1668 89/<- %esp 5/r32/ebp +1669 5d/pop-to-ebp +1670 c3/return +1671 +1672 test-emit-subx-statement-select-primitive: +1673 # Select the right primitive between overloads. +1674 # foo <- increment +1675 # => +1676 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1677 # +1678 # There's a variable on the var stack as follows: +1679 # name: 'foo' +1680 # type: int +1681 # register: 'eax' +1682 # +1683 # There's two primitives, as follows: +1684 # - name: 'increment' +1685 # out: int/reg +1686 # value: 'ff 0/subop/increment' +1687 # - name: 'increment' +1688 # inout: int/mem +1689 # value: 'ff 0/subop/increment' +1690 # +1691 # There's nothing in functions. +1692 # +1693 # . prologue +1694 55/push-ebp +1695 89/<- %ebp 4/r32/esp +1696 # setup +1697 (clear-stream _test-output-stream) +1698 (clear-stream _test-output-buffered-file->buffer) +1699 # var-foo/ecx : var in eax +1700 68/push "eax"/imm32/register +1701 68/push 0/imm32/no-stack-offset +1702 68/push 1/imm32/block-depth +1703 68/push 1/imm32/type-int +1704 68/push "foo"/imm32 +1705 89/<- %ecx 4/r32/esp +1706 # vars/edx : (stack 1) +1707 51/push-ecx/var-foo +1708 68/push 1/imm32/data-length +1709 68/push 1/imm32/top +1710 89/<- %edx 4/r32/esp +1711 # real-outputs/edi : (list var) +1712 68/push 0/imm32/next +1713 51/push-ecx/var-foo +1714 89/<- %edi 4/r32/esp +1715 # stmt/esi : statement +1716 68/push 0/imm32/next +1717 57/push-edi/outputs +1718 68/push 0/imm32/inouts +1719 68/push "increment"/imm32/operation +1720 89/<- %esi 4/r32/esp +1721 # formal-var/ebx : var in any register +1722 68/push Any-register/imm32 +1723 68/push 0/imm32/no-stack-offset +1724 68/push 1/imm32/block-depth +1725 68/push 1/imm32/type-int +1726 68/push "dummy"/imm32 +1727 89/<- %ebx 4/r32/esp +1728 # formal-outputs/ebx : (list var) +1729 68/push 0/imm32/next +1730 53/push-ebx/formal-var +1731 89/<- %ebx 4/r32/esp +1732 # primitive1/ebx : primitive +1733 68/push 0/imm32/next +1734 68/push 0/imm32/no-imm32 +1735 68/push 0/imm32/no-r32 +1736 68/push 3/imm32/rm32-in-first-output +1737 68/push "ff 0/subop/increment"/imm32/subx-name +1738 53/push-ebx/outputs/formal-outputs +1739 68/push 0/imm32/inouts +1740 68/push "increment"/imm32/name +1741 89/<- %ebx 4/r32/esp +1742 # primitives/ebx : primitive +1743 53/push-ebx/next +1744 68/push 0/imm32/no-imm32 +1745 68/push 0/imm32/no-r32 +1746 68/push 1/imm32/rm32-is-first-inout +1747 68/push "ff 0/subop/increment"/imm32/subx-name +1748 68/push 0/imm32/outputs +1749 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +1750 68/push "increment"/imm32/name +1751 89/<- %ebx 4/r32/esp +1752 # convert +1753 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1754 (flush _test-output-buffered-file) +1755 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1761 # check output +1762 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive/0") +1763 # . reclaim locals +1764 81 0/subop/add %esp 0x48/imm32 +1765 # . epilogue +1766 89/<- %esp 5/r32/ebp +1767 5d/pop-to-ebp +1768 c3/return +1769 +1770 test-emit-subx-statement-select-primitive-2: +1771 # Select the right primitive between overloads. +1772 # foo <- increment +1773 # => +1774 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1775 # +1776 # There's a variable on the var stack as follows: +1777 # name: 'foo' +1778 # type: int +1779 # register: 'eax' +1780 # +1781 # There's two primitives, as follows: +1782 # - name: 'increment' +1783 # out: int/reg +1784 # value: 'ff 0/subop/increment' +1785 # - name: 'increment' +1786 # inout: int/mem +1787 # value: 'ff 0/subop/increment' +1788 # +1789 # There's nothing in functions. +1790 # +1791 # . prologue +1792 55/push-ebp +1793 89/<- %ebp 4/r32/esp +1794 # setup +1795 (clear-stream _test-output-stream) +1796 (clear-stream _test-output-buffered-file->buffer) +1797 # var-foo/ecx : var in eax +1798 68/push "eax"/imm32/register +1799 68/push 0/imm32/no-stack-offset +1800 68/push 1/imm32/block-depth +1801 68/push 1/imm32/type-int +1802 68/push "foo"/imm32 +1803 89/<- %ecx 4/r32/esp +1804 # vars/edx : (stack 1) +1805 51/push-ecx/var-foo +1806 68/push 1/imm32/data-length +1807 68/push 1/imm32/top +1808 89/<- %edx 4/r32/esp +1809 # inouts/edi : (list var) +1810 68/push 0/imm32/next +1811 51/push-ecx/var-foo +1812 89/<- %edi 4/r32/esp +1813 # stmt/esi : statement +1814 68/push 0/imm32/next +1815 68/push 0/imm32/outputs +1816 57/push-edi/inouts +1817 68/push "increment"/imm32/operation +1818 89/<- %esi 4/r32/esp +1819 # formal-var/ebx : var in any register +1820 68/push Any-register/imm32 +1821 68/push 0/imm32/no-stack-offset +1822 68/push 1/imm32/block-depth +1823 68/push 1/imm32/type-int +1824 68/push "dummy"/imm32 +1825 89/<- %ebx 4/r32/esp +1826 # operand/ebx : (list var) +1827 68/push 0/imm32/next +1828 53/push-ebx/formal-var +1829 89/<- %ebx 4/r32/esp +1830 # primitive1/ebx : primitive +1831 68/push 0/imm32/next +1832 68/push 0/imm32/no-imm32 +1833 68/push 0/imm32/no-r32 +1834 68/push 3/imm32/rm32-in-first-output +1835 68/push "ff 0/subop/increment"/imm32/subx-name +1836 53/push-ebx/outputs/formal-outputs +1837 68/push 0/imm32/inouts +1838 68/push "increment"/imm32/name +1839 89/<- %ebx 4/r32/esp +1840 # primitives/ebx : primitive +1841 53/push-ebx/next +1842 68/push 0/imm32/no-imm32 +1843 68/push 0/imm32/no-r32 +1844 68/push 1/imm32/rm32-is-first-inout +1845 68/push "ff 0/subop/increment"/imm32/subx-name +1846 68/push 0/imm32/outputs +1847 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +1848 68/push "increment"/imm32/name +1849 89/<- %ebx 4/r32/esp +1850 # convert +1851 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0) +1852 (flush _test-output-buffered-file) +1853 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1859 # check output +1860 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2/0") +1861 # . reclaim locals +1862 81 0/subop/add %esp 0x48/imm32 +1863 # . epilogue +1864 89/<- %esp 5/r32/ebp +1865 5d/pop-to-ebp +1866 c3/return +1867 +1868 test-emit-subx-statement-select-primitive-using-global-primitives: +1869 # Select the right primitive between overloads. +1870 # foo <- increment +1871 # => +1872 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1873 # +1874 # There's a variable on the var stack as follows: +1875 # name: 'foo' +1876 # type: int +1877 # register: 'eax' +1878 # +1879 # Primitives are the global definitions. +1880 # +1881 # There are no functions defined. +1882 # +1883 # . prologue +1884 55/push-ebp +1885 89/<- %ebp 4/r32/esp +1886 # setup +1887 (clear-stream _test-output-stream) +1888 (clear-stream _test-output-buffered-file->buffer) +1889 # var-foo/ecx : var in eax +1890 68/push "eax"/imm32/register +1891 68/push 0/imm32/no-stack-offset +1892 68/push 1/imm32/block-depth +1893 68/push 1/imm32/type-int +1894 68/push "foo"/imm32 +1895 89/<- %ecx 4/r32/esp +1896 # vars/edx : (stack 1) +1897 51/push-ecx/var-foo +1898 68/push 1/imm32/data-length +1899 68/push 1/imm32/top +1900 89/<- %edx 4/r32/esp +1901 # real-outputs/edi : (list var) +1902 68/push 0/imm32/next +1903 51/push-ecx/var-foo +1904 89/<- %edi 4/r32/esp +1905 # stmt/esi : statement +1906 68/push 0/imm32/next +1907 57/push-edi/outputs +1908 68/push 0/imm32/inouts +1909 68/push "increment"/imm32/operation +1910 89/<- %esi 4/r32/esp +1911 # convert +1912 (emit-subx-statement _test-output-buffered-file %esi %edx Primitives 0) +1913 (flush _test-output-buffered-file) +1914 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1920 # check output +1921 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive/0") +1922 # . reclaim locals +1923 81 0/subop/add %esp 0x48/imm32 +1924 # . epilogue +1925 89/<- %esp 5/r32/ebp +1926 5d/pop-to-ebp +1927 c3/return +1928 +1929 test-emit-subx-statement-select-primitive-using-global-primitives-2: +1930 # Select the right primitive between overloads. +1931 # foo <- increment +1932 # => +1933 # ff 0/subop/increment %eax # sub-optimal, but should suffice +1934 # +1935 # There's a variable on the var stack as follows: +1936 # name: 'foo' +1937 # type: int +1938 # register: 'eax' +1939 # +1940 # Primitives are the global definitions. +1941 # +1942 # There are no functions defined. +1943 # +1944 # . prologue +1945 55/push-ebp +1946 89/<- %ebp 4/r32/esp +1947 # setup +1948 (clear-stream _test-output-stream) +1949 (clear-stream _test-output-buffered-file->buffer) +1950 # var-foo/ecx : var in eax +1951 68/push "eax"/imm32/register +1952 68/push 0/imm32/no-stack-offset +1953 68/push 1/imm32/block-depth +1954 68/push 1/imm32/type-int +1955 68/push "foo"/imm32 +1956 89/<- %ecx 4/r32/esp +1957 # vars/edx : (stack 1) +1958 51/push-ecx/var-foo +1959 68/push 1/imm32/data-length +1960 68/push 1/imm32/top +1961 89/<- %edx 4/r32/esp +1962 # inouts/edi : (list var) +1963 68/push 0/imm32/next +1964 51/push-ecx/var-foo +1965 89/<- %edi 4/r32/esp +1966 # stmt/esi : statement +1967 68/push 0/imm32/next +1968 68/push 0/imm32/outputs +1969 57/push-edi/inouts +1970 68/push "increment"/imm32/operation +1971 89/<- %esi 4/r32/esp +1972 # convert +1973 (emit-subx-statement _test-output-buffered-file %esi %edx Primitives 0) +1974 (flush _test-output-buffered-file) +1975 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1981 # check output +1982 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2/0") +1983 # . reclaim locals +1984 81 0/subop/add %esp 0x48/imm32 +1985 # . epilogue +1986 89/<- %esp 5/r32/ebp +1987 5d/pop-to-ebp +1988 c3/return +1989 +1990 test-emit-subx-statement-function-call: +1991 # Call a function on a variable on the stack. +1992 # f foo +1993 # => +1994 # (f2 *(ebp-8)) +1995 # (Changing the function name supports overloading in general, but here it +1996 # just serves to help disambiguate things.) +1997 # +1998 # There's a variable on the var stack as follows: +1999 # name: 'foo' +2000 # type: int +2001 # stack-offset: -8 +2002 # +2003 # There's nothing in primitives. +2004 # +2005 # There's a function with this info: +2006 # name: 'f' +2007 # inout: int/mem +2008 # value: 'f2' +2009 # +2010 # . prologue +2011 55/push-ebp +2012 89/<- %ebp 4/r32/esp +2013 # setup +2014 (clear-stream _test-output-stream) +2015 (clear-stream _test-output-buffered-file->buffer) +2016 # var-foo/ecx : var +2017 68/push 0/imm32/no-register +2018 68/push -8/imm32/stack-offset +2019 68/push 0/imm32/block-depth +2020 68/push 1/imm32/type-int +2021 68/push "foo"/imm32 +2022 89/<- %ecx 4/r32/esp +2023 # vars/edx = (stack 1) +2024 51/push-ecx/var-foo +2025 68/push 1/imm32/data-length +2026 68/push 1/imm32/top +2027 89/<- %edx 4/r32/esp +2028 # operands/esi : (list var) +2029 68/push 0/imm32/next +2030 51/push-ecx/var-foo +2031 89/<- %esi 4/r32/esp +2032 # stmt/esi : statement +2033 68/push 0/imm32/next +2034 68/push 0/imm32/outputs +2035 56/push-esi/inouts +2036 68/push "f"/imm32/operation +2037 89/<- %esi 4/r32/esp +2038 # functions/ebx : function +2039 68/push 0/imm32/next +2040 68/push 0/imm32/body +2041 68/push 0/imm32/outputs +2042 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +2043 68/push "f2"/imm32/subx-name +2044 68/push "f"/imm32/name +2045 89/<- %ebx 4/r32/esp +2046 # convert +2047 (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx) +2048 (flush _test-output-buffered-file) +2049 +-- 6 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +2055 # check output +2056 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call/0") +2057 # . reclaim locals +2058 81 0/subop/add %esp 0x3c/imm32 +2059 # . epilogue +2060 89/<- %esp 5/r32/ebp +2061 5d/pop-to-ebp +2062 c3/return +2063 +2064 emit-subx-prologue: # out : (address buffered-file) +2065 # . prologue +2066 55/push-ebp +2067 89/<- %ebp 4/r32/esp +2068 # +2069 (write-buffered *(ebp+8) "# . prologue\n") +2070 (write-buffered *(ebp+8) "55/push-ebp\n") +2071 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n") +2072 $emit-subx-prologue:end: +2073 # . epilogue +2074 89/<- %esp 5/r32/ebp +2075 5d/pop-to-ebp +2076 c3/return +2077 +2078 emit-subx-epilogue: # out : (address buffered-file) +2079 # . prologue +2080 55/push-ebp +2081 89/<- %ebp 4/r32/esp +2082 # +2083 (write-buffered *(ebp+8) "# . epilogue\n") +2084 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n") +2085 (write-buffered *(ebp+8) "5d/pop-to-ebp\n") +2086 (write-buffered *(ebp+8) "c3/return\n") +2087 $emit-subx-epilogue:end: +2088 # . epilogue +2089 89/<- %esp 5/r32/ebp +2090 5d/pop-to-ebp +2091 c3/return -- cgit 1.4.1-2-gfad0